Loading services/surfaceflinger/CompositionEngine/src/Display.cpp +1 −10 Original line number Diff line number Diff line Loading @@ -163,16 +163,7 @@ std::unique_ptr<compositionengine::OutputLayer> Display::createOutputLayer( if (const auto halDisplayId = HalDisplayId::tryCast(mId); outputLayer && !mIsDisconnected && halDisplayId) { auto& hwc = getCompositionEngine().getHwComposer(); // Note: For the moment we ensure it is safe to take a reference to the // HWComposer implementation by destroying all the OutputLayers (and // hence the HWC2::Layers they own) before setting a new HWComposer. See // for example SurfaceFlinger::updateVrFlinger(). // TODO(b/121291683): Make this safer. auto hwcLayer = std::shared_ptr<HWC2::Layer>(hwc.createLayer(*halDisplayId), [&hwc, id = *halDisplayId](HWC2::Layer* layer) { hwc.destroyLayer(id, layer); }); auto hwcLayer = hwc.createLayer(*halDisplayId); ALOGE_IF(!hwcLayer, "Failed to create a HWC layer for a HWC supported display %s", getName().c_str()); outputLayer->setHwcLayer(std::move(hwcLayer)); Loading services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp +3 −4 Original line number Diff line number Diff line Loading @@ -486,16 +486,15 @@ using DisplayCreateOutputLayerTest = FullDisplayImplTestCommon; TEST_F(DisplayCreateOutputLayerTest, setsHwcLayer) { sp<mock::LayerFE> layerFE = new StrictMock<mock::LayerFE>(); StrictMock<HWC2::mock::Layer> hwcLayer; auto hwcLayer = std::make_shared<StrictMock<HWC2::mock::Layer>>(); EXPECT_CALL(mHwComposer, createLayer(HalDisplayId(DEFAULT_DISPLAY_ID))) .WillOnce(Return(&hwcLayer)); .WillOnce(Return(hwcLayer)); auto outputLayer = mDisplay->createOutputLayer(layerFE); EXPECT_EQ(&hwcLayer, outputLayer->getHwcLayer()); EXPECT_EQ(hwcLayer.get(), outputLayer->getHwcLayer()); EXPECT_CALL(mHwComposer, destroyLayer(HalDisplayId(DEFAULT_DISPLAY_ID), &hwcLayer)); outputLayer.reset(); } Loading services/surfaceflinger/CompositionEngine/tests/MockHWComposer.h +1 −2 Original line number Diff line number Diff line Loading @@ -52,8 +52,7 @@ public: std::optional<PhysicalDisplayId>)); MOCK_METHOD2(allocatePhysicalDisplay, void(hal::HWDisplayId, PhysicalDisplayId)); MOCK_METHOD1(createLayer, HWC2::Layer*(HalDisplayId)); MOCK_METHOD2(destroyLayer, void(HalDisplayId, HWC2::Layer*)); MOCK_METHOD1(createLayer, std::shared_ptr<HWC2::Layer>(HalDisplayId)); MOCK_METHOD3(getDeviceCompositionChanges, status_t(HalDisplayId, bool, std::optional<android::HWComposer::DeviceRequestedChanges>*)); Loading services/surfaceflinger/DisplayHardware/HWC2.cpp +142 −52 Original line number Diff line number Diff line Loading @@ -78,7 +78,19 @@ Display::Display(android::Hwc2::Composer& composer, } Display::~Display() { mLayers.clear(); // Note: The calls to onOwningDisplayDestroyed() are allowed (and expected) // to call Display::onLayerDestroyed(). As that call removes entries from // mLayers, we do not want to have a for loop directly over it here. Since // the end goal is an empty mLayers anyway, we just go ahead and swap an // initially empty local container with mLayers, and then enumerate // the contents of the local container. Layers destroyingLayers; std::swap(mLayers, destroyingLayers); for (const auto& [_, weakLayer] : destroyingLayers) { if (std::shared_ptr layer = weakLayer.lock()) { layer->onOwningDisplayDestroyed(); } } Error error = Error::NONE; const char* msg; Loading Loading @@ -110,29 +122,21 @@ Error Display::acceptChanges() return static_cast<Error>(intError); } Error Display::createLayer(HWC2::Layer** outLayer) { if (!outLayer) { return Error::BAD_PARAMETER; } base::expected<std::shared_ptr<HWC2::Layer>, hal::Error> Display::createLayer() { HWLayerId layerId = 0; auto intError = mComposer.createLayer(mId, &layerId); auto error = static_cast<Error>(intError); if (error != Error::NONE) { return error; return base::unexpected(error); } auto layer = std::make_unique<impl::Layer>(mComposer, mCapabilities, mId, layerId); *outLayer = layer.get(); mLayers.emplace(layerId, std::move(layer)); return Error::NONE; auto layer = std::make_shared<impl::Layer>(mComposer, mCapabilities, *this, layerId); mLayers.emplace(layerId, layer); return layer; } Error Display::destroyLayer(HWC2::Layer* layer) { if (!layer) { return Error::BAD_PARAMETER; } mLayers.erase(layer->getId()); return Error::NONE; void Display::onLayerDestroyed(hal::HWLayerId layerId) { mLayers.erase(layerId); } bool Display::isVsyncPeriodSwitchSupported() const { Loading Loading @@ -161,7 +165,7 @@ Error Display::getChangedCompositionTypes(std::unordered_map<HWC2::Layer*, Compo auto type = types[element]; ALOGV("getChangedCompositionTypes: adding %" PRIu64 " %s", layer->getId(), to_string(type).c_str()); outTypes->emplace(layer, type); outTypes->emplace(layer.get(), type); } else { ALOGE("getChangedCompositionTypes: invalid layer %" PRIu64 " found" " on display %" PRIu64, layerIds[element], mId); Loading Loading @@ -254,7 +258,7 @@ Error Display::getRequests(HWC2::DisplayRequest* outDisplayRequests, if (layer) { auto layerRequest = static_cast<LayerRequest>(layerRequests[element]); outLayerRequests->emplace(layer, layerRequest); outLayerRequests->emplace(layer.get(), layerRequest); } else { ALOGE("getRequests: invalid layer %" PRIu64 " found on display %" PRIu64, layerIds[element], mId); Loading Loading @@ -340,7 +344,7 @@ Error Display::getReleaseFences(std::unordered_map<HWC2::Layer*, sp<Fence>>* out auto layer = getLayerById(layerIds[element]); if (layer) { sp<Fence> fence(new Fence(fenceFds[element])); releaseFences.emplace(layer, fence); releaseFences.emplace(layer.get(), fence); } else { ALOGE("getReleaseFences: invalid layer %" PRIu64 " found on display %" PRIu64, layerIds[element], mId); Loading Loading @@ -550,12 +554,9 @@ void Display::setConnected(bool connected) { // Other Display methods HWC2::Layer* Display::getLayerById(HWLayerId id) const { if (mLayers.count(id) == 0) { return nullptr; } return mLayers.at(id).get(); std::shared_ptr<HWC2::Layer> Display::getLayerById(HWLayerId id) const { auto it = mLayers.find(id); return it != mLayers.end() ? it->second.lock() : nullptr; } } // namespace impl Loading @@ -566,47 +567,78 @@ Layer::~Layer() = default; namespace impl { Layer::Layer(android::Hwc2::Composer& composer, const std::unordered_set<Capability>& capabilities, HWDisplayId displayId, HWLayerId layerId) HWC2::Display& display, HWLayerId layerId) : mComposer(composer), mCapabilities(capabilities), mDisplayId(displayId), mDisplay(&display), mId(layerId), mColorMatrix(android::mat4()) { ALOGV("Created layer %" PRIu64 " on display %" PRIu64, layerId, displayId); ALOGV("Created layer %" PRIu64 " on display %" PRIu64, layerId, display.getId()); } Layer::~Layer() { auto intError = mComposer.destroyLayer(mDisplayId, mId); onOwningDisplayDestroyed(); } void Layer::onOwningDisplayDestroyed() { // Note: onOwningDisplayDestroyed() may be called to perform cleanup by // either the Layer dtor or by the Display dtor and must be safe to call // from either path. In particular, the call to Display::onLayerDestroyed() // is expected to be safe to do, if (CC_UNLIKELY(!mDisplay)) { return; } mDisplay->onLayerDestroyed(mId); // Note: If the HWC display was actually disconnected, these calls are will // return an error. We always make them as there may be other reasons for // the HWC2::Display to be destroyed. auto intError = mComposer.destroyLayer(mDisplay->getId(), mId); auto error = static_cast<Error>(intError); ALOGE_IF(error != Error::NONE, "destroyLayer(%" PRIu64 ", %" PRIu64 ")" " failed: %s (%d)", mDisplayId, mId, to_string(error).c_str(), intError); mDisplay->getId(), mId, to_string(error).c_str(), intError); mDisplay = nullptr; } Error Layer::setCursorPosition(int32_t x, int32_t y) { auto intError = mComposer.setCursorPosition(mDisplayId, mId, x, y); if (CC_UNLIKELY(!mDisplay)) { return Error::BAD_DISPLAY; } auto intError = mComposer.setCursorPosition(mDisplay->getId(), mId, x, y); return static_cast<Error>(intError); } Error Layer::setBuffer(uint32_t slot, const sp<GraphicBuffer>& buffer, const sp<Fence>& acquireFence) { if (CC_UNLIKELY(!mDisplay)) { return Error::BAD_DISPLAY; } if (buffer == nullptr && mBufferSlot == slot) { return Error::NONE; } mBufferSlot = slot; int32_t fenceFd = acquireFence->dup(); auto intError = mComposer.setLayerBuffer(mDisplayId, mId, slot, buffer, fenceFd); auto intError = mComposer.setLayerBuffer(mDisplay->getId(), mId, slot, buffer, fenceFd); return static_cast<Error>(intError); } Error Layer::setSurfaceDamage(const Region& damage) { if (CC_UNLIKELY(!mDisplay)) { return Error::BAD_DISPLAY; } if (damage.isRect() && mDamageRegion.isRect() && (damage.getBounds() == mDamageRegion.getBounds())) { return Error::NONE; Loading @@ -617,8 +649,8 @@ Error Layer::setSurfaceDamage(const Region& damage) // rects for HWC Hwc2::Error intError = Hwc2::Error::NONE; if (damage.isRect() && damage.getBounds() == Rect::INVALID_RECT) { intError = mComposer.setLayerSurfaceDamage(mDisplayId, mId, std::vector<Hwc2::IComposerClient::Rect>()); intError = mComposer.setLayerSurfaceDamage(mDisplay->getId(), mId, std::vector<Hwc2::IComposerClient::Rect>()); } else { size_t rectCount = 0; auto rectArray = damage.getArray(&rectCount); Loading @@ -629,7 +661,7 @@ Error Layer::setSurfaceDamage(const Region& damage) rectArray[rect].right, rectArray[rect].bottom}); } intError = mComposer.setLayerSurfaceDamage(mDisplayId, mId, hwcRects); intError = mComposer.setLayerSurfaceDamage(mDisplay->getId(), mId, hwcRects); } return static_cast<Error>(intError); Loading @@ -637,34 +669,54 @@ Error Layer::setSurfaceDamage(const Region& damage) Error Layer::setBlendMode(BlendMode mode) { auto intError = mComposer.setLayerBlendMode(mDisplayId, mId, mode); if (CC_UNLIKELY(!mDisplay)) { return Error::BAD_DISPLAY; } auto intError = mComposer.setLayerBlendMode(mDisplay->getId(), mId, mode); return static_cast<Error>(intError); } Error Layer::setColor(Color color) { auto intError = mComposer.setLayerColor(mDisplayId, mId, color); if (CC_UNLIKELY(!mDisplay)) { return Error::BAD_DISPLAY; } auto intError = mComposer.setLayerColor(mDisplay->getId(), mId, color); return static_cast<Error>(intError); } Error Layer::setCompositionType(Composition type) { auto intError = mComposer.setLayerCompositionType(mDisplayId, mId, type); if (CC_UNLIKELY(!mDisplay)) { return Error::BAD_DISPLAY; } auto intError = mComposer.setLayerCompositionType(mDisplay->getId(), mId, type); return static_cast<Error>(intError); } Error Layer::setDataspace(Dataspace dataspace) { if (CC_UNLIKELY(!mDisplay)) { return Error::BAD_DISPLAY; } if (dataspace == mDataSpace) { return Error::NONE; } mDataSpace = dataspace; auto intError = mComposer.setLayerDataspace(mDisplayId, mId, mDataSpace); auto intError = mComposer.setLayerDataspace(mDisplay->getId(), mId, mDataSpace); return static_cast<Error>(intError); } Error Layer::setPerFrameMetadata(const int32_t supportedPerFrameMetadata, const android::HdrMetadata& metadata) { if (CC_UNLIKELY(!mDisplay)) { return Error::BAD_DISPLAY; } if (metadata == mHdrMetadata) { return Error::NONE; } Loading Loading @@ -705,7 +757,7 @@ Error Layer::setPerFrameMetadata(const int32_t supportedPerFrameMetadata, } Error error = static_cast<Error>( mComposer.setLayerPerFrameMetadata(mDisplayId, mId, perFrameMetadatas)); mComposer.setLayerPerFrameMetadata(mDisplay->getId(), mId, perFrameMetadatas)); if (validTypes & HdrMetadata::HDR10PLUS) { if (CC_UNLIKELY(mHdrMetadata.hdr10plus.size() == 0)) { Loading @@ -715,8 +767,9 @@ Error Layer::setPerFrameMetadata(const int32_t supportedPerFrameMetadata, std::vector<Hwc2::PerFrameMetadataBlob> perFrameMetadataBlobs; perFrameMetadataBlobs.push_back( {Hwc2::PerFrameMetadataKey::HDR10_PLUS_SEI, mHdrMetadata.hdr10plus}); Error setMetadataBlobsError = static_cast<Error>( mComposer.setLayerPerFrameMetadataBlobs(mDisplayId, mId, perFrameMetadataBlobs)); Error setMetadataBlobsError = static_cast<Error>(mComposer.setLayerPerFrameMetadataBlobs(mDisplay->getId(), mId, perFrameMetadataBlobs)); if (error == Error::NONE) { return setMetadataBlobsError; } Loading @@ -726,46 +779,70 @@ Error Layer::setPerFrameMetadata(const int32_t supportedPerFrameMetadata, Error Layer::setDisplayFrame(const Rect& frame) { if (CC_UNLIKELY(!mDisplay)) { return Error::BAD_DISPLAY; } Hwc2::IComposerClient::Rect hwcRect{frame.left, frame.top, frame.right, frame.bottom}; auto intError = mComposer.setLayerDisplayFrame(mDisplayId, mId, hwcRect); auto intError = mComposer.setLayerDisplayFrame(mDisplay->getId(), mId, hwcRect); return static_cast<Error>(intError); } Error Layer::setPlaneAlpha(float alpha) { auto intError = mComposer.setLayerPlaneAlpha(mDisplayId, mId, alpha); if (CC_UNLIKELY(!mDisplay)) { return Error::BAD_DISPLAY; } auto intError = mComposer.setLayerPlaneAlpha(mDisplay->getId(), mId, alpha); return static_cast<Error>(intError); } Error Layer::setSidebandStream(const native_handle_t* stream) { if (CC_UNLIKELY(!mDisplay)) { return Error::BAD_DISPLAY; } if (mCapabilities.count(Capability::SIDEBAND_STREAM) == 0) { ALOGE("Attempted to call setSidebandStream without checking that the " "device supports sideband streams"); return Error::UNSUPPORTED; } auto intError = mComposer.setLayerSidebandStream(mDisplayId, mId, stream); auto intError = mComposer.setLayerSidebandStream(mDisplay->getId(), mId, stream); return static_cast<Error>(intError); } Error Layer::setSourceCrop(const FloatRect& crop) { if (CC_UNLIKELY(!mDisplay)) { return Error::BAD_DISPLAY; } Hwc2::IComposerClient::FRect hwcRect{ crop.left, crop.top, crop.right, crop.bottom}; auto intError = mComposer.setLayerSourceCrop(mDisplayId, mId, hwcRect); auto intError = mComposer.setLayerSourceCrop(mDisplay->getId(), mId, hwcRect); return static_cast<Error>(intError); } Error Layer::setTransform(Transform transform) { if (CC_UNLIKELY(!mDisplay)) { return Error::BAD_DISPLAY; } auto intTransform = static_cast<Hwc2::Transform>(transform); auto intError = mComposer.setLayerTransform(mDisplayId, mId, intTransform); auto intError = mComposer.setLayerTransform(mDisplay->getId(), mId, intTransform); return static_cast<Error>(intError); } Error Layer::setVisibleRegion(const Region& region) { if (CC_UNLIKELY(!mDisplay)) { return Error::BAD_DISPLAY; } if (region.isRect() && mVisibleRegion.isRect() && (region.getBounds() == mVisibleRegion.getBounds())) { return Error::NONE; Loading @@ -781,22 +858,30 @@ Error Layer::setVisibleRegion(const Region& region) rectArray[rect].right, rectArray[rect].bottom}); } auto intError = mComposer.setLayerVisibleRegion(mDisplayId, mId, hwcRects); auto intError = mComposer.setLayerVisibleRegion(mDisplay->getId(), mId, hwcRects); return static_cast<Error>(intError); } Error Layer::setZOrder(uint32_t z) { auto intError = mComposer.setLayerZOrder(mDisplayId, mId, z); if (CC_UNLIKELY(!mDisplay)) { return Error::BAD_DISPLAY; } auto intError = mComposer.setLayerZOrder(mDisplay->getId(), mId, z); return static_cast<Error>(intError); } // Composer HAL 2.3 Error Layer::setColorTransform(const android::mat4& matrix) { if (CC_UNLIKELY(!mDisplay)) { return Error::BAD_DISPLAY; } if (matrix == mColorMatrix) { return Error::NONE; } auto intError = mComposer.setLayerColorTransform(mDisplayId, mId, matrix.asArray()); auto intError = mComposer.setLayerColorTransform(mDisplay->getId(), mId, matrix.asArray()); Error error = static_cast<Error>(intError); if (error != Error::NONE) { return error; Loading @@ -808,7 +893,12 @@ Error Layer::setColorTransform(const android::mat4& matrix) { // Composer HAL 2.4 Error Layer::setLayerGenericMetadata(const std::string& name, bool mandatory, const std::vector<uint8_t>& value) { auto intError = mComposer.setLayerGenericMetadata(mDisplayId, mId, name, mandatory, value); if (CC_UNLIKELY(!mDisplay)) { return Error::BAD_DISPLAY; } auto intError = mComposer.setLayerGenericMetadata(mDisplay->getId(), mId, name, mandatory, value); return static_cast<Error>(intError); } Loading services/surfaceflinger/DisplayHardware/HWC2.h +20 −13 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ #pragma once #include <android-base/expected.h> #include <gui/HdrMetadata.h> #include <math/mat4.h> #include <ui/HdrCapabilities.h> Loading Loading @@ -80,10 +81,11 @@ public: virtual void setConnected(bool connected) = 0; // For use by Device only virtual const std::unordered_set<hal::DisplayCapability>& getCapabilities() const = 0; virtual bool isVsyncPeriodSwitchSupported() const = 0; virtual void onLayerDestroyed(hal::HWLayerId layerId) = 0; [[clang::warn_unused_result]] virtual hal::Error acceptChanges() = 0; [[clang::warn_unused_result]] virtual hal::Error createLayer(Layer** outLayer) = 0; [[clang::warn_unused_result]] virtual hal::Error destroyLayer(Layer* layer) = 0; [[clang::warn_unused_result]] virtual base::expected<std::shared_ptr<HWC2::Layer>, hal::Error> createLayer() = 0; [[clang::warn_unused_result]] virtual hal::Error getChangedCompositionTypes( std::unordered_map<Layer*, hal::Composition>* outTypes) = 0; [[clang::warn_unused_result]] virtual hal::Error getColorModes( Loading Loading @@ -148,6 +150,8 @@ public: namespace impl { class Layer; class Display : public HWC2::Display { public: Display(android::Hwc2::Composer&, const std::unordered_set<hal::Capability>&, hal::HWDisplayId, Loading @@ -156,10 +160,9 @@ public: // Required by HWC2 hal::Error acceptChanges() override; hal::Error createLayer(Layer** outLayer) override; hal::Error destroyLayer(Layer*) override; base::expected<std::shared_ptr<HWC2::Layer>, hal::Error> createLayer() override; hal::Error getChangedCompositionTypes( std::unordered_map<Layer*, hal::Composition>* outTypes) override; std::unordered_map<HWC2::Layer*, hal::Composition>* outTypes) override; hal::Error getColorModes(std::vector<hal::ColorMode>* outModes) const override; // Returns a bitmask which contains HdrMetadata::Type::*. int32_t getSupportedPerFrameMetadata() const override; Loading @@ -170,7 +173,7 @@ public: hal::Error getName(std::string* outName) const override; hal::Error getRequests( hal::DisplayRequest* outDisplayRequests, std::unordered_map<Layer*, hal::LayerRequest>* outLayerRequests) override; std::unordered_map<HWC2::Layer*, hal::LayerRequest>* outLayerRequests) override; hal::Error getConnectionType(ui::DisplayConnectionType*) const override; hal::Error supportsDoze(bool* outSupport) const override; hal::Error getHdrCapabilities(android::HdrCapabilities* outCapabilities) const override; Loading @@ -181,8 +184,8 @@ public: uint64_t maxFrames) const override; hal::Error getDisplayedContentSample(uint64_t maxFrames, uint64_t timestamp, android::DisplayedFrameStats* outStats) const override; hal::Error getReleaseFences( std::unordered_map<Layer*, android::sp<android::Fence>>* outFences) const override; hal::Error getReleaseFences(std::unordered_map<HWC2::Layer*, android::sp<android::Fence>>* outFences) const override; hal::Error present(android::sp<android::Fence>* outPresentFence) override; hal::Error setClientTarget(uint32_t slot, const android::sp<android::GraphicBuffer>& target, const android::sp<android::Fence>& acquireFence, Loading Loading @@ -214,13 +217,14 @@ public: const std::unordered_set<hal::DisplayCapability>& getCapabilities() const override { return mDisplayCapabilities; }; virtual bool isVsyncPeriodSwitchSupported() const override; bool isVsyncPeriodSwitchSupported() const override; void onLayerDestroyed(hal::HWLayerId layerId) override; private: // This may fail (and return a null pointer) if no layer with this ID exists // on this display Layer* getLayerById(hal::HWLayerId) const; std::shared_ptr<HWC2::Layer> getLayerById(hal::HWLayerId id) const; friend android::TestableSurfaceFlinger; Loading @@ -236,7 +240,8 @@ private: hal::DisplayType mType; bool mIsConnected = false; std::unordered_map<hal::HWLayerId, std::unique_ptr<Layer>> mLayers; using Layers = std::unordered_map<hal::HWLayerId, std::weak_ptr<HWC2::impl::Layer>>; Layers mLayers; std::once_flag mDisplayCapabilityQueryFlag; std::unordered_set<hal::DisplayCapability> mDisplayCapabilities; Loading Loading @@ -291,10 +296,12 @@ namespace impl { class Layer : public HWC2::Layer { public: Layer(android::Hwc2::Composer& composer, const std::unordered_set<hal::Capability>& capabilities, hal::HWDisplayId displayId, const std::unordered_set<hal::Capability>& capabilities, HWC2::Display& display, hal::HWLayerId layerId); ~Layer() override; void onOwningDisplayDestroyed(); hal::HWLayerId getId() const override { return mId; } hal::Error setCursorPosition(int32_t x, int32_t y) override; Loading Loading @@ -330,7 +337,7 @@ private: android::Hwc2::Composer& mComposer; const std::unordered_set<hal::Capability>& mCapabilities; hal::HWDisplayId mDisplayId; HWC2::Display* mDisplay; hal::HWLayerId mId; // Cached HWC2 data, to ensure the same commands aren't sent to the HWC Loading Loading
services/surfaceflinger/CompositionEngine/src/Display.cpp +1 −10 Original line number Diff line number Diff line Loading @@ -163,16 +163,7 @@ std::unique_ptr<compositionengine::OutputLayer> Display::createOutputLayer( if (const auto halDisplayId = HalDisplayId::tryCast(mId); outputLayer && !mIsDisconnected && halDisplayId) { auto& hwc = getCompositionEngine().getHwComposer(); // Note: For the moment we ensure it is safe to take a reference to the // HWComposer implementation by destroying all the OutputLayers (and // hence the HWC2::Layers they own) before setting a new HWComposer. See // for example SurfaceFlinger::updateVrFlinger(). // TODO(b/121291683): Make this safer. auto hwcLayer = std::shared_ptr<HWC2::Layer>(hwc.createLayer(*halDisplayId), [&hwc, id = *halDisplayId](HWC2::Layer* layer) { hwc.destroyLayer(id, layer); }); auto hwcLayer = hwc.createLayer(*halDisplayId); ALOGE_IF(!hwcLayer, "Failed to create a HWC layer for a HWC supported display %s", getName().c_str()); outputLayer->setHwcLayer(std::move(hwcLayer)); Loading
services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp +3 −4 Original line number Diff line number Diff line Loading @@ -486,16 +486,15 @@ using DisplayCreateOutputLayerTest = FullDisplayImplTestCommon; TEST_F(DisplayCreateOutputLayerTest, setsHwcLayer) { sp<mock::LayerFE> layerFE = new StrictMock<mock::LayerFE>(); StrictMock<HWC2::mock::Layer> hwcLayer; auto hwcLayer = std::make_shared<StrictMock<HWC2::mock::Layer>>(); EXPECT_CALL(mHwComposer, createLayer(HalDisplayId(DEFAULT_DISPLAY_ID))) .WillOnce(Return(&hwcLayer)); .WillOnce(Return(hwcLayer)); auto outputLayer = mDisplay->createOutputLayer(layerFE); EXPECT_EQ(&hwcLayer, outputLayer->getHwcLayer()); EXPECT_EQ(hwcLayer.get(), outputLayer->getHwcLayer()); EXPECT_CALL(mHwComposer, destroyLayer(HalDisplayId(DEFAULT_DISPLAY_ID), &hwcLayer)); outputLayer.reset(); } Loading
services/surfaceflinger/CompositionEngine/tests/MockHWComposer.h +1 −2 Original line number Diff line number Diff line Loading @@ -52,8 +52,7 @@ public: std::optional<PhysicalDisplayId>)); MOCK_METHOD2(allocatePhysicalDisplay, void(hal::HWDisplayId, PhysicalDisplayId)); MOCK_METHOD1(createLayer, HWC2::Layer*(HalDisplayId)); MOCK_METHOD2(destroyLayer, void(HalDisplayId, HWC2::Layer*)); MOCK_METHOD1(createLayer, std::shared_ptr<HWC2::Layer>(HalDisplayId)); MOCK_METHOD3(getDeviceCompositionChanges, status_t(HalDisplayId, bool, std::optional<android::HWComposer::DeviceRequestedChanges>*)); Loading
services/surfaceflinger/DisplayHardware/HWC2.cpp +142 −52 Original line number Diff line number Diff line Loading @@ -78,7 +78,19 @@ Display::Display(android::Hwc2::Composer& composer, } Display::~Display() { mLayers.clear(); // Note: The calls to onOwningDisplayDestroyed() are allowed (and expected) // to call Display::onLayerDestroyed(). As that call removes entries from // mLayers, we do not want to have a for loop directly over it here. Since // the end goal is an empty mLayers anyway, we just go ahead and swap an // initially empty local container with mLayers, and then enumerate // the contents of the local container. Layers destroyingLayers; std::swap(mLayers, destroyingLayers); for (const auto& [_, weakLayer] : destroyingLayers) { if (std::shared_ptr layer = weakLayer.lock()) { layer->onOwningDisplayDestroyed(); } } Error error = Error::NONE; const char* msg; Loading Loading @@ -110,29 +122,21 @@ Error Display::acceptChanges() return static_cast<Error>(intError); } Error Display::createLayer(HWC2::Layer** outLayer) { if (!outLayer) { return Error::BAD_PARAMETER; } base::expected<std::shared_ptr<HWC2::Layer>, hal::Error> Display::createLayer() { HWLayerId layerId = 0; auto intError = mComposer.createLayer(mId, &layerId); auto error = static_cast<Error>(intError); if (error != Error::NONE) { return error; return base::unexpected(error); } auto layer = std::make_unique<impl::Layer>(mComposer, mCapabilities, mId, layerId); *outLayer = layer.get(); mLayers.emplace(layerId, std::move(layer)); return Error::NONE; auto layer = std::make_shared<impl::Layer>(mComposer, mCapabilities, *this, layerId); mLayers.emplace(layerId, layer); return layer; } Error Display::destroyLayer(HWC2::Layer* layer) { if (!layer) { return Error::BAD_PARAMETER; } mLayers.erase(layer->getId()); return Error::NONE; void Display::onLayerDestroyed(hal::HWLayerId layerId) { mLayers.erase(layerId); } bool Display::isVsyncPeriodSwitchSupported() const { Loading Loading @@ -161,7 +165,7 @@ Error Display::getChangedCompositionTypes(std::unordered_map<HWC2::Layer*, Compo auto type = types[element]; ALOGV("getChangedCompositionTypes: adding %" PRIu64 " %s", layer->getId(), to_string(type).c_str()); outTypes->emplace(layer, type); outTypes->emplace(layer.get(), type); } else { ALOGE("getChangedCompositionTypes: invalid layer %" PRIu64 " found" " on display %" PRIu64, layerIds[element], mId); Loading Loading @@ -254,7 +258,7 @@ Error Display::getRequests(HWC2::DisplayRequest* outDisplayRequests, if (layer) { auto layerRequest = static_cast<LayerRequest>(layerRequests[element]); outLayerRequests->emplace(layer, layerRequest); outLayerRequests->emplace(layer.get(), layerRequest); } else { ALOGE("getRequests: invalid layer %" PRIu64 " found on display %" PRIu64, layerIds[element], mId); Loading Loading @@ -340,7 +344,7 @@ Error Display::getReleaseFences(std::unordered_map<HWC2::Layer*, sp<Fence>>* out auto layer = getLayerById(layerIds[element]); if (layer) { sp<Fence> fence(new Fence(fenceFds[element])); releaseFences.emplace(layer, fence); releaseFences.emplace(layer.get(), fence); } else { ALOGE("getReleaseFences: invalid layer %" PRIu64 " found on display %" PRIu64, layerIds[element], mId); Loading Loading @@ -550,12 +554,9 @@ void Display::setConnected(bool connected) { // Other Display methods HWC2::Layer* Display::getLayerById(HWLayerId id) const { if (mLayers.count(id) == 0) { return nullptr; } return mLayers.at(id).get(); std::shared_ptr<HWC2::Layer> Display::getLayerById(HWLayerId id) const { auto it = mLayers.find(id); return it != mLayers.end() ? it->second.lock() : nullptr; } } // namespace impl Loading @@ -566,47 +567,78 @@ Layer::~Layer() = default; namespace impl { Layer::Layer(android::Hwc2::Composer& composer, const std::unordered_set<Capability>& capabilities, HWDisplayId displayId, HWLayerId layerId) HWC2::Display& display, HWLayerId layerId) : mComposer(composer), mCapabilities(capabilities), mDisplayId(displayId), mDisplay(&display), mId(layerId), mColorMatrix(android::mat4()) { ALOGV("Created layer %" PRIu64 " on display %" PRIu64, layerId, displayId); ALOGV("Created layer %" PRIu64 " on display %" PRIu64, layerId, display.getId()); } Layer::~Layer() { auto intError = mComposer.destroyLayer(mDisplayId, mId); onOwningDisplayDestroyed(); } void Layer::onOwningDisplayDestroyed() { // Note: onOwningDisplayDestroyed() may be called to perform cleanup by // either the Layer dtor or by the Display dtor and must be safe to call // from either path. In particular, the call to Display::onLayerDestroyed() // is expected to be safe to do, if (CC_UNLIKELY(!mDisplay)) { return; } mDisplay->onLayerDestroyed(mId); // Note: If the HWC display was actually disconnected, these calls are will // return an error. We always make them as there may be other reasons for // the HWC2::Display to be destroyed. auto intError = mComposer.destroyLayer(mDisplay->getId(), mId); auto error = static_cast<Error>(intError); ALOGE_IF(error != Error::NONE, "destroyLayer(%" PRIu64 ", %" PRIu64 ")" " failed: %s (%d)", mDisplayId, mId, to_string(error).c_str(), intError); mDisplay->getId(), mId, to_string(error).c_str(), intError); mDisplay = nullptr; } Error Layer::setCursorPosition(int32_t x, int32_t y) { auto intError = mComposer.setCursorPosition(mDisplayId, mId, x, y); if (CC_UNLIKELY(!mDisplay)) { return Error::BAD_DISPLAY; } auto intError = mComposer.setCursorPosition(mDisplay->getId(), mId, x, y); return static_cast<Error>(intError); } Error Layer::setBuffer(uint32_t slot, const sp<GraphicBuffer>& buffer, const sp<Fence>& acquireFence) { if (CC_UNLIKELY(!mDisplay)) { return Error::BAD_DISPLAY; } if (buffer == nullptr && mBufferSlot == slot) { return Error::NONE; } mBufferSlot = slot; int32_t fenceFd = acquireFence->dup(); auto intError = mComposer.setLayerBuffer(mDisplayId, mId, slot, buffer, fenceFd); auto intError = mComposer.setLayerBuffer(mDisplay->getId(), mId, slot, buffer, fenceFd); return static_cast<Error>(intError); } Error Layer::setSurfaceDamage(const Region& damage) { if (CC_UNLIKELY(!mDisplay)) { return Error::BAD_DISPLAY; } if (damage.isRect() && mDamageRegion.isRect() && (damage.getBounds() == mDamageRegion.getBounds())) { return Error::NONE; Loading @@ -617,8 +649,8 @@ Error Layer::setSurfaceDamage(const Region& damage) // rects for HWC Hwc2::Error intError = Hwc2::Error::NONE; if (damage.isRect() && damage.getBounds() == Rect::INVALID_RECT) { intError = mComposer.setLayerSurfaceDamage(mDisplayId, mId, std::vector<Hwc2::IComposerClient::Rect>()); intError = mComposer.setLayerSurfaceDamage(mDisplay->getId(), mId, std::vector<Hwc2::IComposerClient::Rect>()); } else { size_t rectCount = 0; auto rectArray = damage.getArray(&rectCount); Loading @@ -629,7 +661,7 @@ Error Layer::setSurfaceDamage(const Region& damage) rectArray[rect].right, rectArray[rect].bottom}); } intError = mComposer.setLayerSurfaceDamage(mDisplayId, mId, hwcRects); intError = mComposer.setLayerSurfaceDamage(mDisplay->getId(), mId, hwcRects); } return static_cast<Error>(intError); Loading @@ -637,34 +669,54 @@ Error Layer::setSurfaceDamage(const Region& damage) Error Layer::setBlendMode(BlendMode mode) { auto intError = mComposer.setLayerBlendMode(mDisplayId, mId, mode); if (CC_UNLIKELY(!mDisplay)) { return Error::BAD_DISPLAY; } auto intError = mComposer.setLayerBlendMode(mDisplay->getId(), mId, mode); return static_cast<Error>(intError); } Error Layer::setColor(Color color) { auto intError = mComposer.setLayerColor(mDisplayId, mId, color); if (CC_UNLIKELY(!mDisplay)) { return Error::BAD_DISPLAY; } auto intError = mComposer.setLayerColor(mDisplay->getId(), mId, color); return static_cast<Error>(intError); } Error Layer::setCompositionType(Composition type) { auto intError = mComposer.setLayerCompositionType(mDisplayId, mId, type); if (CC_UNLIKELY(!mDisplay)) { return Error::BAD_DISPLAY; } auto intError = mComposer.setLayerCompositionType(mDisplay->getId(), mId, type); return static_cast<Error>(intError); } Error Layer::setDataspace(Dataspace dataspace) { if (CC_UNLIKELY(!mDisplay)) { return Error::BAD_DISPLAY; } if (dataspace == mDataSpace) { return Error::NONE; } mDataSpace = dataspace; auto intError = mComposer.setLayerDataspace(mDisplayId, mId, mDataSpace); auto intError = mComposer.setLayerDataspace(mDisplay->getId(), mId, mDataSpace); return static_cast<Error>(intError); } Error Layer::setPerFrameMetadata(const int32_t supportedPerFrameMetadata, const android::HdrMetadata& metadata) { if (CC_UNLIKELY(!mDisplay)) { return Error::BAD_DISPLAY; } if (metadata == mHdrMetadata) { return Error::NONE; } Loading Loading @@ -705,7 +757,7 @@ Error Layer::setPerFrameMetadata(const int32_t supportedPerFrameMetadata, } Error error = static_cast<Error>( mComposer.setLayerPerFrameMetadata(mDisplayId, mId, perFrameMetadatas)); mComposer.setLayerPerFrameMetadata(mDisplay->getId(), mId, perFrameMetadatas)); if (validTypes & HdrMetadata::HDR10PLUS) { if (CC_UNLIKELY(mHdrMetadata.hdr10plus.size() == 0)) { Loading @@ -715,8 +767,9 @@ Error Layer::setPerFrameMetadata(const int32_t supportedPerFrameMetadata, std::vector<Hwc2::PerFrameMetadataBlob> perFrameMetadataBlobs; perFrameMetadataBlobs.push_back( {Hwc2::PerFrameMetadataKey::HDR10_PLUS_SEI, mHdrMetadata.hdr10plus}); Error setMetadataBlobsError = static_cast<Error>( mComposer.setLayerPerFrameMetadataBlobs(mDisplayId, mId, perFrameMetadataBlobs)); Error setMetadataBlobsError = static_cast<Error>(mComposer.setLayerPerFrameMetadataBlobs(mDisplay->getId(), mId, perFrameMetadataBlobs)); if (error == Error::NONE) { return setMetadataBlobsError; } Loading @@ -726,46 +779,70 @@ Error Layer::setPerFrameMetadata(const int32_t supportedPerFrameMetadata, Error Layer::setDisplayFrame(const Rect& frame) { if (CC_UNLIKELY(!mDisplay)) { return Error::BAD_DISPLAY; } Hwc2::IComposerClient::Rect hwcRect{frame.left, frame.top, frame.right, frame.bottom}; auto intError = mComposer.setLayerDisplayFrame(mDisplayId, mId, hwcRect); auto intError = mComposer.setLayerDisplayFrame(mDisplay->getId(), mId, hwcRect); return static_cast<Error>(intError); } Error Layer::setPlaneAlpha(float alpha) { auto intError = mComposer.setLayerPlaneAlpha(mDisplayId, mId, alpha); if (CC_UNLIKELY(!mDisplay)) { return Error::BAD_DISPLAY; } auto intError = mComposer.setLayerPlaneAlpha(mDisplay->getId(), mId, alpha); return static_cast<Error>(intError); } Error Layer::setSidebandStream(const native_handle_t* stream) { if (CC_UNLIKELY(!mDisplay)) { return Error::BAD_DISPLAY; } if (mCapabilities.count(Capability::SIDEBAND_STREAM) == 0) { ALOGE("Attempted to call setSidebandStream without checking that the " "device supports sideband streams"); return Error::UNSUPPORTED; } auto intError = mComposer.setLayerSidebandStream(mDisplayId, mId, stream); auto intError = mComposer.setLayerSidebandStream(mDisplay->getId(), mId, stream); return static_cast<Error>(intError); } Error Layer::setSourceCrop(const FloatRect& crop) { if (CC_UNLIKELY(!mDisplay)) { return Error::BAD_DISPLAY; } Hwc2::IComposerClient::FRect hwcRect{ crop.left, crop.top, crop.right, crop.bottom}; auto intError = mComposer.setLayerSourceCrop(mDisplayId, mId, hwcRect); auto intError = mComposer.setLayerSourceCrop(mDisplay->getId(), mId, hwcRect); return static_cast<Error>(intError); } Error Layer::setTransform(Transform transform) { if (CC_UNLIKELY(!mDisplay)) { return Error::BAD_DISPLAY; } auto intTransform = static_cast<Hwc2::Transform>(transform); auto intError = mComposer.setLayerTransform(mDisplayId, mId, intTransform); auto intError = mComposer.setLayerTransform(mDisplay->getId(), mId, intTransform); return static_cast<Error>(intError); } Error Layer::setVisibleRegion(const Region& region) { if (CC_UNLIKELY(!mDisplay)) { return Error::BAD_DISPLAY; } if (region.isRect() && mVisibleRegion.isRect() && (region.getBounds() == mVisibleRegion.getBounds())) { return Error::NONE; Loading @@ -781,22 +858,30 @@ Error Layer::setVisibleRegion(const Region& region) rectArray[rect].right, rectArray[rect].bottom}); } auto intError = mComposer.setLayerVisibleRegion(mDisplayId, mId, hwcRects); auto intError = mComposer.setLayerVisibleRegion(mDisplay->getId(), mId, hwcRects); return static_cast<Error>(intError); } Error Layer::setZOrder(uint32_t z) { auto intError = mComposer.setLayerZOrder(mDisplayId, mId, z); if (CC_UNLIKELY(!mDisplay)) { return Error::BAD_DISPLAY; } auto intError = mComposer.setLayerZOrder(mDisplay->getId(), mId, z); return static_cast<Error>(intError); } // Composer HAL 2.3 Error Layer::setColorTransform(const android::mat4& matrix) { if (CC_UNLIKELY(!mDisplay)) { return Error::BAD_DISPLAY; } if (matrix == mColorMatrix) { return Error::NONE; } auto intError = mComposer.setLayerColorTransform(mDisplayId, mId, matrix.asArray()); auto intError = mComposer.setLayerColorTransform(mDisplay->getId(), mId, matrix.asArray()); Error error = static_cast<Error>(intError); if (error != Error::NONE) { return error; Loading @@ -808,7 +893,12 @@ Error Layer::setColorTransform(const android::mat4& matrix) { // Composer HAL 2.4 Error Layer::setLayerGenericMetadata(const std::string& name, bool mandatory, const std::vector<uint8_t>& value) { auto intError = mComposer.setLayerGenericMetadata(mDisplayId, mId, name, mandatory, value); if (CC_UNLIKELY(!mDisplay)) { return Error::BAD_DISPLAY; } auto intError = mComposer.setLayerGenericMetadata(mDisplay->getId(), mId, name, mandatory, value); return static_cast<Error>(intError); } Loading
services/surfaceflinger/DisplayHardware/HWC2.h +20 −13 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ #pragma once #include <android-base/expected.h> #include <gui/HdrMetadata.h> #include <math/mat4.h> #include <ui/HdrCapabilities.h> Loading Loading @@ -80,10 +81,11 @@ public: virtual void setConnected(bool connected) = 0; // For use by Device only virtual const std::unordered_set<hal::DisplayCapability>& getCapabilities() const = 0; virtual bool isVsyncPeriodSwitchSupported() const = 0; virtual void onLayerDestroyed(hal::HWLayerId layerId) = 0; [[clang::warn_unused_result]] virtual hal::Error acceptChanges() = 0; [[clang::warn_unused_result]] virtual hal::Error createLayer(Layer** outLayer) = 0; [[clang::warn_unused_result]] virtual hal::Error destroyLayer(Layer* layer) = 0; [[clang::warn_unused_result]] virtual base::expected<std::shared_ptr<HWC2::Layer>, hal::Error> createLayer() = 0; [[clang::warn_unused_result]] virtual hal::Error getChangedCompositionTypes( std::unordered_map<Layer*, hal::Composition>* outTypes) = 0; [[clang::warn_unused_result]] virtual hal::Error getColorModes( Loading Loading @@ -148,6 +150,8 @@ public: namespace impl { class Layer; class Display : public HWC2::Display { public: Display(android::Hwc2::Composer&, const std::unordered_set<hal::Capability>&, hal::HWDisplayId, Loading @@ -156,10 +160,9 @@ public: // Required by HWC2 hal::Error acceptChanges() override; hal::Error createLayer(Layer** outLayer) override; hal::Error destroyLayer(Layer*) override; base::expected<std::shared_ptr<HWC2::Layer>, hal::Error> createLayer() override; hal::Error getChangedCompositionTypes( std::unordered_map<Layer*, hal::Composition>* outTypes) override; std::unordered_map<HWC2::Layer*, hal::Composition>* outTypes) override; hal::Error getColorModes(std::vector<hal::ColorMode>* outModes) const override; // Returns a bitmask which contains HdrMetadata::Type::*. int32_t getSupportedPerFrameMetadata() const override; Loading @@ -170,7 +173,7 @@ public: hal::Error getName(std::string* outName) const override; hal::Error getRequests( hal::DisplayRequest* outDisplayRequests, std::unordered_map<Layer*, hal::LayerRequest>* outLayerRequests) override; std::unordered_map<HWC2::Layer*, hal::LayerRequest>* outLayerRequests) override; hal::Error getConnectionType(ui::DisplayConnectionType*) const override; hal::Error supportsDoze(bool* outSupport) const override; hal::Error getHdrCapabilities(android::HdrCapabilities* outCapabilities) const override; Loading @@ -181,8 +184,8 @@ public: uint64_t maxFrames) const override; hal::Error getDisplayedContentSample(uint64_t maxFrames, uint64_t timestamp, android::DisplayedFrameStats* outStats) const override; hal::Error getReleaseFences( std::unordered_map<Layer*, android::sp<android::Fence>>* outFences) const override; hal::Error getReleaseFences(std::unordered_map<HWC2::Layer*, android::sp<android::Fence>>* outFences) const override; hal::Error present(android::sp<android::Fence>* outPresentFence) override; hal::Error setClientTarget(uint32_t slot, const android::sp<android::GraphicBuffer>& target, const android::sp<android::Fence>& acquireFence, Loading Loading @@ -214,13 +217,14 @@ public: const std::unordered_set<hal::DisplayCapability>& getCapabilities() const override { return mDisplayCapabilities; }; virtual bool isVsyncPeriodSwitchSupported() const override; bool isVsyncPeriodSwitchSupported() const override; void onLayerDestroyed(hal::HWLayerId layerId) override; private: // This may fail (and return a null pointer) if no layer with this ID exists // on this display Layer* getLayerById(hal::HWLayerId) const; std::shared_ptr<HWC2::Layer> getLayerById(hal::HWLayerId id) const; friend android::TestableSurfaceFlinger; Loading @@ -236,7 +240,8 @@ private: hal::DisplayType mType; bool mIsConnected = false; std::unordered_map<hal::HWLayerId, std::unique_ptr<Layer>> mLayers; using Layers = std::unordered_map<hal::HWLayerId, std::weak_ptr<HWC2::impl::Layer>>; Layers mLayers; std::once_flag mDisplayCapabilityQueryFlag; std::unordered_set<hal::DisplayCapability> mDisplayCapabilities; Loading Loading @@ -291,10 +296,12 @@ namespace impl { class Layer : public HWC2::Layer { public: Layer(android::Hwc2::Composer& composer, const std::unordered_set<hal::Capability>& capabilities, hal::HWDisplayId displayId, const std::unordered_set<hal::Capability>& capabilities, HWC2::Display& display, hal::HWLayerId layerId); ~Layer() override; void onOwningDisplayDestroyed(); hal::HWLayerId getId() const override { return mId; } hal::Error setCursorPosition(int32_t x, int32_t y) override; Loading Loading @@ -330,7 +337,7 @@ private: android::Hwc2::Composer& mComposer; const std::unordered_set<hal::Capability>& mCapabilities; hal::HWDisplayId mDisplayId; HWC2::Display* mDisplay; hal::HWLayerId mId; // Cached HWC2 data, to ensure the same commands aren't sent to the HWC Loading