Loading services/surfaceflinger/CompositionEngine/src/Output.cpp +37 −29 Original line number Original line Diff line number Diff line Loading @@ -815,6 +815,43 @@ std::optional<base::unique_fd> Output::composeSurfaces( OutputCompositionState& outputCompositionState = editState(); OutputCompositionState& outputCompositionState = editState(); const TracedOrdinal<bool> hasClientComposition = {"hasClientComposition", const TracedOrdinal<bool> hasClientComposition = {"hasClientComposition", outputState.usesClientComposition}; outputState.usesClientComposition}; auto& renderEngine = getCompositionEngine().getRenderEngine(); const bool supportsProtectedContent = renderEngine.supportsProtectedContent(); // If we the display is secure, protected content support is enabled, and at // least one layer has protected content, we need to use a secure back // buffer. if (outputState.isSecure && supportsProtectedContent) { auto layers = getOutputLayersOrderedByZ(); bool needsProtected = std::any_of(layers.begin(), layers.end(), [](auto* layer) { return layer->getLayerFE().getCompositionState()->hasProtectedContent; }); if (needsProtected != renderEngine.isProtected()) { renderEngine.useProtectedContext(needsProtected); } if (needsProtected != mRenderSurface->isProtected() && needsProtected == renderEngine.isProtected()) { mRenderSurface->setProtected(needsProtected); } } base::unique_fd fd; sp<GraphicBuffer> buf; // If we aren't doing client composition on this output, but do have a // flipClientTarget request for this frame on this output, we still need to // dequeue a buffer. if (hasClientComposition || outputState.flipClientTarget) { buf = mRenderSurface->dequeueBuffer(&fd); if (buf == nullptr) { ALOGW("Dequeuing buffer for display [%s] failed, bailing out of " "client composition for this frame", mName.c_str()); return {}; } } base::unique_fd readyFence; base::unique_fd readyFence; if (!hasClientComposition) { if (!hasClientComposition) { setExpensiveRenderingExpected(false); setExpensiveRenderingExpected(false); Loading @@ -823,9 +860,6 @@ std::optional<base::unique_fd> Output::composeSurfaces( ALOGV("hasClientComposition"); ALOGV("hasClientComposition"); auto& renderEngine = getCompositionEngine().getRenderEngine(); const bool supportsProtectedContent = renderEngine.supportsProtectedContent(); renderengine::DisplaySettings clientCompositionDisplay; renderengine::DisplaySettings clientCompositionDisplay; clientCompositionDisplay.physicalDisplay = outputState.destinationClip; clientCompositionDisplay.physicalDisplay = outputState.destinationClip; clientCompositionDisplay.clip = outputState.sourceClip; clientCompositionDisplay.clip = outputState.sourceClip; Loading @@ -851,32 +885,6 @@ std::optional<base::unique_fd> Output::composeSurfaces( clientCompositionDisplay.outputDataspace); clientCompositionDisplay.outputDataspace); appendRegionFlashRequests(debugRegion, clientCompositionLayers); appendRegionFlashRequests(debugRegion, clientCompositionLayers); // If we the display is secure, protected content support is enabled, and at // least one layer has protected content, we need to use a secure back // buffer. if (outputState.isSecure && supportsProtectedContent) { auto layers = getOutputLayersOrderedByZ(); bool needsProtected = std::any_of(layers.begin(), layers.end(), [](auto* layer) { return layer->getLayerFE().getCompositionState()->hasProtectedContent; }); if (needsProtected != renderEngine.isProtected()) { renderEngine.useProtectedContext(needsProtected); } if (needsProtected != mRenderSurface->isProtected() && needsProtected == renderEngine.isProtected()) { mRenderSurface->setProtected(needsProtected); } } base::unique_fd fd; sp<GraphicBuffer> buf = mRenderSurface->dequeueBuffer(&fd); if (buf == nullptr) { ALOGW("Dequeuing buffer for display [%s] failed, bailing out of " "client composition for this frame", mName.c_str()); return std::nullopt; } // Check if the client composition requests were rendered into the provided graphic buffer. If // Check if the client composition requests were rendered into the provided graphic buffer. If // so, we can reuse the buffer and avoid client composition. // so, we can reuse the buffer and avoid client composition. if (mClientCompositionRequestCache) { if (mClientCompositionRequestCache) { Loading services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp +4 −0 Original line number Original line Diff line number Diff line Loading @@ -30,6 +30,7 @@ #include <compositionengine/mock/OutputLayer.h> #include <compositionengine/mock/OutputLayer.h> #include <compositionengine/mock/RenderSurface.h> #include <compositionengine/mock/RenderSurface.h> #include <gtest/gtest.h> #include <gtest/gtest.h> #include <renderengine/mock/RenderEngine.h> #include <ui/DisplayInfo.h> #include <ui/DisplayInfo.h> #include <ui/Rect.h> #include <ui/Rect.h> Loading Loading @@ -156,6 +157,8 @@ struct DisplayTestCommon : public testing::Test { DisplayTestCommon() { DisplayTestCommon() { EXPECT_CALL(mCompositionEngine, getHwComposer()).WillRepeatedly(ReturnRef(mHwComposer)); EXPECT_CALL(mCompositionEngine, getHwComposer()).WillRepeatedly(ReturnRef(mHwComposer)); EXPECT_CALL(mCompositionEngine, getRenderEngine()).WillRepeatedly(ReturnRef(mRenderEngine)); EXPECT_CALL(mRenderEngine, supportsProtectedContent()).WillRepeatedly(Return(false)); } } DisplayCreationArgs getDisplayCreationArgsForPhysicalHWCDisplay() { DisplayCreationArgs getDisplayCreationArgsForPhysicalHWCDisplay() { Loading @@ -182,6 +185,7 @@ struct DisplayTestCommon : public testing::Test { StrictMock<android::mock::HWComposer> mHwComposer; StrictMock<android::mock::HWComposer> mHwComposer; StrictMock<Hwc2::mock::PowerAdvisor> mPowerAdvisor; StrictMock<Hwc2::mock::PowerAdvisor> mPowerAdvisor; StrictMock<renderengine::mock::RenderEngine> mRenderEngine; StrictMock<mock::CompositionEngine> mCompositionEngine; StrictMock<mock::CompositionEngine> mCompositionEngine; sp<mock::NativeWindow> mNativeWindow = new StrictMock<mock::NativeWindow>(); sp<mock::NativeWindow> mNativeWindow = new StrictMock<mock::NativeWindow>(); }; }; Loading services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp +29 −7 Original line number Original line Diff line number Diff line Loading @@ -2797,6 +2797,7 @@ struct OutputComposeSurfacesTest : public testing::Test { mOutput.mState.usesClientComposition = true; mOutput.mState.usesClientComposition = true; mOutput.mState.usesDeviceComposition = false; mOutput.mState.usesDeviceComposition = false; mOutput.mState.reusedClientComposition = false; mOutput.mState.reusedClientComposition = false; mOutput.mState.flipClientTarget = false; EXPECT_CALL(mOutput, getCompositionEngine()).WillRepeatedly(ReturnRef(mCompositionEngine)); EXPECT_CALL(mOutput, getCompositionEngine()).WillRepeatedly(ReturnRef(mCompositionEngine)); EXPECT_CALL(mCompositionEngine, getRenderEngine()).WillRepeatedly(ReturnRef(mRenderEngine)); EXPECT_CALL(mCompositionEngine, getRenderEngine()).WillRepeatedly(ReturnRef(mRenderEngine)); Loading Loading @@ -2868,19 +2869,40 @@ const HdrCapabilities OutputComposeSurfacesTest:: TEST_F(OutputComposeSurfacesTest, doesNothingButSignalNoExpensiveRenderingIfNoClientComposition) { TEST_F(OutputComposeSurfacesTest, doesNothingButSignalNoExpensiveRenderingIfNoClientComposition) { mOutput.mState.usesClientComposition = false; mOutput.mState.usesClientComposition = false; EXPECT_CALL(mRenderEngine, supportsProtectedContent()).WillRepeatedly(Return(false)); EXPECT_CALL(mOutput, setExpensiveRenderingExpected(false)); EXPECT_CALL(mOutput, setExpensiveRenderingExpected(false)); verify().execute().expectAFenceWasReturned(); verify().execute().expectAFenceWasReturned(); } } TEST_F(OutputComposeSurfacesTest, doesMinimalWorkIfDequeueBufferFails) { TEST_F(OutputComposeSurfacesTest, EXPECT_CALL(mOutput, getSkipColorTransform()).WillRepeatedly(Return(false)); dequeuesABufferIfNoClientCompositionButFlipClientTargetRequested) { EXPECT_CALL(*mDisplayColorProfile, hasWideColorGamut()).WillRepeatedly(Return(true)); mOutput.mState.usesClientComposition = false; mOutput.mState.flipClientTarget = true; EXPECT_CALL(mRenderEngine, supportsProtectedContent()).WillRepeatedly(Return(false)); EXPECT_CALL(*mRenderSurface, dequeueBuffer(_)).WillOnce(Return(mOutputBuffer)); EXPECT_CALL(mOutput, setExpensiveRenderingExpected(false)); verify().execute().expectAFenceWasReturned(); } TEST_F(OutputComposeSurfacesTest, doesMinimalWorkIfDequeueBufferFailsForClientComposition) { EXPECT_CALL(mRenderEngine, supportsProtectedContent()).WillRepeatedly(Return(false)); EXPECT_CALL(*mRenderSurface, dequeueBuffer(_)).WillOnce(Return(nullptr)); verify().execute().expectNoFenceWasReturned(); } TEST_F(OutputComposeSurfacesTest, doesMinimalWorkIfDequeueBufferFailsForNoClientCompositionButFlipClientTargetRequested) { mOutput.mState.usesClientComposition = false; mOutput.mState.flipClientTarget = true; EXPECT_CALL(mRenderEngine, supportsProtectedContent()).WillRepeatedly(Return(false)); EXPECT_CALL(mRenderEngine, supportsProtectedContent()).WillRepeatedly(Return(false)); EXPECT_CALL(mOutput, generateClientCompositionRequests(_, _, kDefaultOutputDataspace)) .WillRepeatedly(Return(std::vector<LayerFE::LayerSettings>{})); EXPECT_CALL(mOutput, appendRegionFlashRequests(RegionEq(kDebugRegion), _)) .WillRepeatedly(Return()); EXPECT_CALL(*mRenderSurface, dequeueBuffer(_)).WillOnce(Return(nullptr)); EXPECT_CALL(*mRenderSurface, dequeueBuffer(_)).WillOnce(Return(nullptr)); Loading services/surfaceflinger/DisplayHardware/HWC2.cpp +1 −1 Original line number Original line Diff line number Diff line Loading @@ -349,7 +349,7 @@ Error Display::getName(std::string* outName) const Error Display::getRequests(HWC2::DisplayRequest* outDisplayRequests, Error Display::getRequests(HWC2::DisplayRequest* outDisplayRequests, std::unordered_map<HWC2::Layer*, LayerRequest>* outLayerRequests) { std::unordered_map<HWC2::Layer*, LayerRequest>* outLayerRequests) { uint32_t intDisplayRequests; uint32_t intDisplayRequests = 0; std::vector<Hwc2::Layer> layerIds; std::vector<Hwc2::Layer> layerIds; std::vector<uint32_t> layerRequests; std::vector<uint32_t> layerRequests; auto intError = mComposer.getDisplayRequests( auto intError = mComposer.getDisplayRequests( Loading Loading
services/surfaceflinger/CompositionEngine/src/Output.cpp +37 −29 Original line number Original line Diff line number Diff line Loading @@ -815,6 +815,43 @@ std::optional<base::unique_fd> Output::composeSurfaces( OutputCompositionState& outputCompositionState = editState(); OutputCompositionState& outputCompositionState = editState(); const TracedOrdinal<bool> hasClientComposition = {"hasClientComposition", const TracedOrdinal<bool> hasClientComposition = {"hasClientComposition", outputState.usesClientComposition}; outputState.usesClientComposition}; auto& renderEngine = getCompositionEngine().getRenderEngine(); const bool supportsProtectedContent = renderEngine.supportsProtectedContent(); // If we the display is secure, protected content support is enabled, and at // least one layer has protected content, we need to use a secure back // buffer. if (outputState.isSecure && supportsProtectedContent) { auto layers = getOutputLayersOrderedByZ(); bool needsProtected = std::any_of(layers.begin(), layers.end(), [](auto* layer) { return layer->getLayerFE().getCompositionState()->hasProtectedContent; }); if (needsProtected != renderEngine.isProtected()) { renderEngine.useProtectedContext(needsProtected); } if (needsProtected != mRenderSurface->isProtected() && needsProtected == renderEngine.isProtected()) { mRenderSurface->setProtected(needsProtected); } } base::unique_fd fd; sp<GraphicBuffer> buf; // If we aren't doing client composition on this output, but do have a // flipClientTarget request for this frame on this output, we still need to // dequeue a buffer. if (hasClientComposition || outputState.flipClientTarget) { buf = mRenderSurface->dequeueBuffer(&fd); if (buf == nullptr) { ALOGW("Dequeuing buffer for display [%s] failed, bailing out of " "client composition for this frame", mName.c_str()); return {}; } } base::unique_fd readyFence; base::unique_fd readyFence; if (!hasClientComposition) { if (!hasClientComposition) { setExpensiveRenderingExpected(false); setExpensiveRenderingExpected(false); Loading @@ -823,9 +860,6 @@ std::optional<base::unique_fd> Output::composeSurfaces( ALOGV("hasClientComposition"); ALOGV("hasClientComposition"); auto& renderEngine = getCompositionEngine().getRenderEngine(); const bool supportsProtectedContent = renderEngine.supportsProtectedContent(); renderengine::DisplaySettings clientCompositionDisplay; renderengine::DisplaySettings clientCompositionDisplay; clientCompositionDisplay.physicalDisplay = outputState.destinationClip; clientCompositionDisplay.physicalDisplay = outputState.destinationClip; clientCompositionDisplay.clip = outputState.sourceClip; clientCompositionDisplay.clip = outputState.sourceClip; Loading @@ -851,32 +885,6 @@ std::optional<base::unique_fd> Output::composeSurfaces( clientCompositionDisplay.outputDataspace); clientCompositionDisplay.outputDataspace); appendRegionFlashRequests(debugRegion, clientCompositionLayers); appendRegionFlashRequests(debugRegion, clientCompositionLayers); // If we the display is secure, protected content support is enabled, and at // least one layer has protected content, we need to use a secure back // buffer. if (outputState.isSecure && supportsProtectedContent) { auto layers = getOutputLayersOrderedByZ(); bool needsProtected = std::any_of(layers.begin(), layers.end(), [](auto* layer) { return layer->getLayerFE().getCompositionState()->hasProtectedContent; }); if (needsProtected != renderEngine.isProtected()) { renderEngine.useProtectedContext(needsProtected); } if (needsProtected != mRenderSurface->isProtected() && needsProtected == renderEngine.isProtected()) { mRenderSurface->setProtected(needsProtected); } } base::unique_fd fd; sp<GraphicBuffer> buf = mRenderSurface->dequeueBuffer(&fd); if (buf == nullptr) { ALOGW("Dequeuing buffer for display [%s] failed, bailing out of " "client composition for this frame", mName.c_str()); return std::nullopt; } // Check if the client composition requests were rendered into the provided graphic buffer. If // Check if the client composition requests were rendered into the provided graphic buffer. If // so, we can reuse the buffer and avoid client composition. // so, we can reuse the buffer and avoid client composition. if (mClientCompositionRequestCache) { if (mClientCompositionRequestCache) { Loading
services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp +4 −0 Original line number Original line Diff line number Diff line Loading @@ -30,6 +30,7 @@ #include <compositionengine/mock/OutputLayer.h> #include <compositionengine/mock/OutputLayer.h> #include <compositionengine/mock/RenderSurface.h> #include <compositionengine/mock/RenderSurface.h> #include <gtest/gtest.h> #include <gtest/gtest.h> #include <renderengine/mock/RenderEngine.h> #include <ui/DisplayInfo.h> #include <ui/DisplayInfo.h> #include <ui/Rect.h> #include <ui/Rect.h> Loading Loading @@ -156,6 +157,8 @@ struct DisplayTestCommon : public testing::Test { DisplayTestCommon() { DisplayTestCommon() { EXPECT_CALL(mCompositionEngine, getHwComposer()).WillRepeatedly(ReturnRef(mHwComposer)); EXPECT_CALL(mCompositionEngine, getHwComposer()).WillRepeatedly(ReturnRef(mHwComposer)); EXPECT_CALL(mCompositionEngine, getRenderEngine()).WillRepeatedly(ReturnRef(mRenderEngine)); EXPECT_CALL(mRenderEngine, supportsProtectedContent()).WillRepeatedly(Return(false)); } } DisplayCreationArgs getDisplayCreationArgsForPhysicalHWCDisplay() { DisplayCreationArgs getDisplayCreationArgsForPhysicalHWCDisplay() { Loading @@ -182,6 +185,7 @@ struct DisplayTestCommon : public testing::Test { StrictMock<android::mock::HWComposer> mHwComposer; StrictMock<android::mock::HWComposer> mHwComposer; StrictMock<Hwc2::mock::PowerAdvisor> mPowerAdvisor; StrictMock<Hwc2::mock::PowerAdvisor> mPowerAdvisor; StrictMock<renderengine::mock::RenderEngine> mRenderEngine; StrictMock<mock::CompositionEngine> mCompositionEngine; StrictMock<mock::CompositionEngine> mCompositionEngine; sp<mock::NativeWindow> mNativeWindow = new StrictMock<mock::NativeWindow>(); sp<mock::NativeWindow> mNativeWindow = new StrictMock<mock::NativeWindow>(); }; }; Loading
services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp +29 −7 Original line number Original line Diff line number Diff line Loading @@ -2797,6 +2797,7 @@ struct OutputComposeSurfacesTest : public testing::Test { mOutput.mState.usesClientComposition = true; mOutput.mState.usesClientComposition = true; mOutput.mState.usesDeviceComposition = false; mOutput.mState.usesDeviceComposition = false; mOutput.mState.reusedClientComposition = false; mOutput.mState.reusedClientComposition = false; mOutput.mState.flipClientTarget = false; EXPECT_CALL(mOutput, getCompositionEngine()).WillRepeatedly(ReturnRef(mCompositionEngine)); EXPECT_CALL(mOutput, getCompositionEngine()).WillRepeatedly(ReturnRef(mCompositionEngine)); EXPECT_CALL(mCompositionEngine, getRenderEngine()).WillRepeatedly(ReturnRef(mRenderEngine)); EXPECT_CALL(mCompositionEngine, getRenderEngine()).WillRepeatedly(ReturnRef(mRenderEngine)); Loading Loading @@ -2868,19 +2869,40 @@ const HdrCapabilities OutputComposeSurfacesTest:: TEST_F(OutputComposeSurfacesTest, doesNothingButSignalNoExpensiveRenderingIfNoClientComposition) { TEST_F(OutputComposeSurfacesTest, doesNothingButSignalNoExpensiveRenderingIfNoClientComposition) { mOutput.mState.usesClientComposition = false; mOutput.mState.usesClientComposition = false; EXPECT_CALL(mRenderEngine, supportsProtectedContent()).WillRepeatedly(Return(false)); EXPECT_CALL(mOutput, setExpensiveRenderingExpected(false)); EXPECT_CALL(mOutput, setExpensiveRenderingExpected(false)); verify().execute().expectAFenceWasReturned(); verify().execute().expectAFenceWasReturned(); } } TEST_F(OutputComposeSurfacesTest, doesMinimalWorkIfDequeueBufferFails) { TEST_F(OutputComposeSurfacesTest, EXPECT_CALL(mOutput, getSkipColorTransform()).WillRepeatedly(Return(false)); dequeuesABufferIfNoClientCompositionButFlipClientTargetRequested) { EXPECT_CALL(*mDisplayColorProfile, hasWideColorGamut()).WillRepeatedly(Return(true)); mOutput.mState.usesClientComposition = false; mOutput.mState.flipClientTarget = true; EXPECT_CALL(mRenderEngine, supportsProtectedContent()).WillRepeatedly(Return(false)); EXPECT_CALL(*mRenderSurface, dequeueBuffer(_)).WillOnce(Return(mOutputBuffer)); EXPECT_CALL(mOutput, setExpensiveRenderingExpected(false)); verify().execute().expectAFenceWasReturned(); } TEST_F(OutputComposeSurfacesTest, doesMinimalWorkIfDequeueBufferFailsForClientComposition) { EXPECT_CALL(mRenderEngine, supportsProtectedContent()).WillRepeatedly(Return(false)); EXPECT_CALL(*mRenderSurface, dequeueBuffer(_)).WillOnce(Return(nullptr)); verify().execute().expectNoFenceWasReturned(); } TEST_F(OutputComposeSurfacesTest, doesMinimalWorkIfDequeueBufferFailsForNoClientCompositionButFlipClientTargetRequested) { mOutput.mState.usesClientComposition = false; mOutput.mState.flipClientTarget = true; EXPECT_CALL(mRenderEngine, supportsProtectedContent()).WillRepeatedly(Return(false)); EXPECT_CALL(mRenderEngine, supportsProtectedContent()).WillRepeatedly(Return(false)); EXPECT_CALL(mOutput, generateClientCompositionRequests(_, _, kDefaultOutputDataspace)) .WillRepeatedly(Return(std::vector<LayerFE::LayerSettings>{})); EXPECT_CALL(mOutput, appendRegionFlashRequests(RegionEq(kDebugRegion), _)) .WillRepeatedly(Return()); EXPECT_CALL(*mRenderSurface, dequeueBuffer(_)).WillOnce(Return(nullptr)); EXPECT_CALL(*mRenderSurface, dequeueBuffer(_)).WillOnce(Return(nullptr)); Loading
services/surfaceflinger/DisplayHardware/HWC2.cpp +1 −1 Original line number Original line Diff line number Diff line Loading @@ -349,7 +349,7 @@ Error Display::getName(std::string* outName) const Error Display::getRequests(HWC2::DisplayRequest* outDisplayRequests, Error Display::getRequests(HWC2::DisplayRequest* outDisplayRequests, std::unordered_map<HWC2::Layer*, LayerRequest>* outLayerRequests) { std::unordered_map<HWC2::Layer*, LayerRequest>* outLayerRequests) { uint32_t intDisplayRequests; uint32_t intDisplayRequests = 0; std::vector<Hwc2::Layer> layerIds; std::vector<Hwc2::Layer> layerIds; std::vector<uint32_t> layerRequests; std::vector<uint32_t> layerRequests; auto intError = mComposer.getDisplayRequests( auto intError = mComposer.getDisplayRequests( Loading