From 2bd7d433250031cba7dba0280c42b12ad3b24037 Mon Sep 17 00:00:00 2001 From: Galia Peycheva Date: Fri, 1 Nov 2019 11:04:42 +0100 Subject: [PATCH] Add controls for ALLM and Content Types to composer hal Also extending the passthrough interface with setLowLatencyMode and setContentType. Bug:132731049 Test: make -j$(nproc) Test: vts-tradefed run vts-hal --skip-device-info -m VtsHalGraphicsComposerV2_4Target Change-Id: I0ec5a5be796700074bdd8cac75cd67f96cd5df58 --- graphics/composer/2.4/IComposerClient.hal | 74 +++++++++++ .../include/composer-hal/2.4/ComposerClient.h | 18 +++ .../include/composer-hal/2.4/ComposerHal.h | 5 + .../include/composer-passthrough/2.4/HwcHal.h | 59 +++++++++ .../composer/2.4/utils/vts/ComposerVts.cpp | 19 +++ .../include/composer-vts/2.4/ComposerVts.h | 7 ++ .../VtsHalGraphicsComposerV2_4TargetTest.cpp | 119 ++++++++++++++++++ 7 files changed, 301 insertions(+) diff --git a/graphics/composer/2.4/IComposerClient.hal b/graphics/composer/2.4/IComposerClient.hal index f23536cd2d..06b4c5e53a 100644 --- a/graphics/composer/2.4/IComposerClient.hal +++ b/graphics/composer/2.4/IComposerClient.hal @@ -48,6 +48,12 @@ interface IComposerClient extends @2.3::IComposerClient { * with protected buffers. */ PROTECTED_CONTENTS = 4, + + /** + * Indicates that both the composer HAL implementation and the given display + * support a low latency mode, such as HDMI 2.1 Auto Low Latency Mode. + */ + AUTO_LOW_LATENCY_MODE = 5, }; /** @@ -64,6 +70,18 @@ interface IComposerClient extends @2.3::IComposerClient { EXTERNAL = 1, }; + enum ContentType : uint32_t { + NONE = 0, + + /** + * These modes correspond to those found in the HDMI 1.4 specification. + */ + GRAPHICS = 1, + PHOTO = 2, + CINEMA = 3, + GAME = 4, + }; + /** * Constraints for changing vsync period. */ @@ -172,4 +190,60 @@ interface IComposerClient extends @2.3::IComposerClient { setActiveConfigWithConstraints(Display display, Config config, VsyncPeriodChangeConstraints vsyncPeriodChangeConstraints) generates (Error error, VsyncPeriodChangeTimeline timeline); + + /** + * Requests the display to enable/disable its low latency mode. + * + * If the display is connected via HDMI 2.1, then Auto Low Latency Mode should be triggered. If + * the display is internally connected and a custom low latency mode is available, that should + * be triggered. + * + * This function should only be called if the display reports support for + * DisplayCapability::AUTO_LOW_LATENCY_MODE from getDisplayCapabilities_2_4. + * + * @return error is NONE upon success. Otherwise, + * BAD_DISPLAY when an invalid display handle was passed in. + * UNSUPPORTED when AUTO_LOW_LATENCY_MODE is not supported by the composer + * implementation or the given display + */ + setAutoLowLatencyMode(Display display, bool on) + generates (Error error); + + /** + * Provides a list of all the content types supported by this display (any of + * ContentType::{GRAPHICS, PHOTO, CINEMA, GAME}). This list must not change after + * initialization. + * + * Content types are introduced in HDMI 1.4 and supporting them is optional. The + * ContentType::NONE is always supported and will not be returned by this method.. + * + * @return error is NONE upon success. Otherwise, + * BAD_DISPLAY when an invalid display handle was passed in. + * @return supportedContentTypes is a list of supported content types. + */ + getSupportedContentTypes(Display display) + generates(Error error, vec supportedContentTypes); + + /** + * Instructs the connected display that the content being shown is of the given type - one of + * GRAPHICS, PHOTO, CINEMA, GAME. + * + * Content types are introduced in HDMI 1.4 and supporting them is optional. If they are + * supported, this signal should switch the display to a mode that is optimal for the given + * type of content. See HDMI 1.4 specification for more information. + * + * If the display is internally connected (not through HDMI), and such modes are available, + * this method should trigger them. + * + * This function should only be called if the display reports support for the corresponding + * content type (ContentType::{GRAPHICS, PHOTO, CINEMA, GAME}) from getSupportedContentTypes. + * ContentType::NONE is supported by default and can always be set. + * + * @return error is NONE upon success. Otherwise, + * BAD_DISPLAY when an invalid display handle was passed in. + * UNSUPPORTED when the given content type is not supported by the composer + * implementation or the given display + */ + setContentType(Display display, ContentType type) + generates (Error error); }; diff --git a/graphics/composer/2.4/utils/hal/include/composer-hal/2.4/ComposerClient.h b/graphics/composer/2.4/utils/hal/include/composer-hal/2.4/ComposerClient.h index 4160ed97bf..dcd959dfb5 100644 --- a/graphics/composer/2.4/utils/hal/include/composer-hal/2.4/ComposerClient.h +++ b/graphics/composer/2.4/utils/hal/include/composer-hal/2.4/ComposerClient.h @@ -139,6 +139,24 @@ class ComposerClientImpl : public V2_3::hal::detail::ComposerClientImpl setAutoLowLatencyMode(Display display, bool on) override { + return mHal->setAutoLowLatencyMode(display, on); + } + + Return getSupportedContentTypes( + Display display, IComposerClient::getSupportedContentTypes_cb hidl_cb) override { + std::vector supportedContentTypes; + Error error = mHal->getSupportedContentTypes(display, &supportedContentTypes); + + hidl_cb(error, supportedContentTypes); + return Void(); + } + + Return setContentType(Display display, + IComposerClient::ContentType contentType) override { + return mHal->setContentType(display, contentType); + } + static std::unique_ptr create(Hal* hal) { auto client = std::make_unique(hal); return client->init() ? std::move(client) : nullptr; diff --git a/graphics/composer/2.4/utils/hal/include/composer-hal/2.4/ComposerHal.h b/graphics/composer/2.4/utils/hal/include/composer-hal/2.4/ComposerHal.h index 89dbe66d60..a1e56ae6ed 100644 --- a/graphics/composer/2.4/utils/hal/include/composer-hal/2.4/ComposerHal.h +++ b/graphics/composer/2.4/utils/hal/include/composer-hal/2.4/ComposerHal.h @@ -67,6 +67,11 @@ class ComposerHal : public V2_3::hal::ComposerHal { Display display, Config config, const IComposerClient::VsyncPeriodChangeConstraints& vsyncPeriodChangeConstraints, VsyncPeriodChangeTimeline* timeline) = 0; + virtual Error setAutoLowLatencyMode(Display display, bool on) = 0; + virtual Error getSupportedContentTypes( + Display display, + std::vector* outSupportedContentTypes) = 0; + virtual Error setContentType(Display display, IComposerClient::ContentType contentType) = 0; }; } // namespace hal diff --git a/graphics/composer/2.4/utils/passthrough/include/composer-passthrough/2.4/HwcHal.h b/graphics/composer/2.4/utils/passthrough/include/composer-passthrough/2.4/HwcHal.h index d59d0d5361..a27582a0e7 100644 --- a/graphics/composer/2.4/utils/passthrough/include/composer-passthrough/2.4/HwcHal.h +++ b/graphics/composer/2.4/utils/passthrough/include/composer-passthrough/2.4/HwcHal.h @@ -167,6 +167,57 @@ class HwcHalImpl : public V2_3::passthrough::detail::HwcHalImpl { return Error::NONE; } + Error setAutoLowLatencyMode(Display display, bool on) override { + if (!mDispatch.setAutoLowLatencyMode) { + return Error::UNSUPPORTED; + } + + int32_t error = mDispatch.setAutoLowLatencyMode(mDevice, display, on); + if (error != HWC2_ERROR_NONE) { + return static_cast(error); + } + return Error::NONE; + } + + Error getSupportedContentTypes( + Display display, + std::vector* outSupportedContentTypes) override { + if (!mDispatch.getSupportedContentTypes) { + return Error::UNSUPPORTED; + } + + uint32_t count = 0; + int32_t error = mDispatch.getSupportedContentTypes(mDevice, display, &count, nullptr); + if (error != HWC2_ERROR_NONE) { + return static_cast(error); + } + + outSupportedContentTypes->resize(count); + + error = mDispatch.getSupportedContentTypes( + mDevice, display, &count, + reinterpret_cast::type*>( + outSupportedContentTypes->data())); + if (error != HWC2_ERROR_NONE) { + *outSupportedContentTypes = std::vector(); + return static_cast(error); + } + return Error::NONE; + } + + Error setContentType(Display display, IComposerClient::ContentType contentType) override { + if (!mDispatch.setContentType) { + return Error::UNSUPPORTED; + } + + int32_t error = + mDispatch.setContentType(mDevice, display, static_cast(contentType)); + if (error != HWC2_ERROR_NONE) { + return static_cast(error); + } + return Error::NONE; + } + protected: bool initDispatch() override { if (!BaseType2_3::initDispatch()) { @@ -179,6 +230,11 @@ class HwcHalImpl : public V2_3::passthrough::detail::HwcHalImpl { &mDispatch.getDisplayVsyncPeriod); this->initOptionalDispatch(HWC2_FUNCTION_SET_ACTIVE_CONFIG_WITH_CONSTRAINTS, &mDispatch.setActiveConfigWithConstraints); + this->initOptionalDispatch(HWC2_FUNCTION_SET_AUTO_LOW_LATENCY_MODE, + &mDispatch.setAutoLowLatencyMode); + this->initOptionalDispatch(HWC2_FUNCTION_GET_SUPPORTED_CONTENT_TYPES, + &mDispatch.getSupportedContentTypes); + this->initOptionalDispatch(HWC2_FUNCTION_SET_CONTENT_TYPE, &mDispatch.setContentType); return true; } @@ -222,6 +278,9 @@ class HwcHalImpl : public V2_3::passthrough::detail::HwcHalImpl { HWC2_PFN_GET_DISPLAY_CONNECTION_TYPE getDisplayConnectionType; HWC2_PFN_GET_DISPLAY_VSYNC_PERIOD getDisplayVsyncPeriod; HWC2_PFN_SET_ACTIVE_CONFIG_WITH_CONSTRAINTS setActiveConfigWithConstraints; + HWC2_PFN_SET_AUTO_LOW_LATENCY_MODE setAutoLowLatencyMode; + HWC2_PFN_GET_SUPPORTED_CONTENT_TYPES getSupportedContentTypes; + HWC2_PFN_SET_CONTENT_TYPE setContentType; } mDispatch = {}; hal::ComposerHal::EventCallback_2_4* mEventCallback_2_4 = nullptr; diff --git a/graphics/composer/2.4/utils/vts/ComposerVts.cpp b/graphics/composer/2.4/utils/vts/ComposerVts.cpp index 35ac23f7ff..5b06d6d3ff 100644 --- a/graphics/composer/2.4/utils/vts/ComposerVts.cpp +++ b/graphics/composer/2.4/utils/vts/ComposerVts.cpp @@ -106,6 +106,25 @@ Error ComposerClient::setActiveConfigWithConstraints( return error; } +Error ComposerClient::setAutoLowLatencyMode(Display display, bool on) { + return mClient->setAutoLowLatencyMode(display, on); +} + +Error ComposerClient::getSupportedContentTypes( + Display display, std::vector* outSupportedContentTypes) { + Error error = Error::NONE; + mClient->getSupportedContentTypes( + display, [&](const auto& tmpError, const auto& tmpSupportedContentTypes) { + error = tmpError; + *outSupportedContentTypes = tmpSupportedContentTypes; + }); + return error; +} + +Error ComposerClient::setContentType(Display display, IComposerClient::ContentType contentType) { + return mClient->setContentType(display, contentType); +} + } // namespace vts } // namespace V2_4 } // namespace composer diff --git a/graphics/composer/2.4/utils/vts/include/composer-vts/2.4/ComposerVts.h b/graphics/composer/2.4/utils/vts/include/composer-vts/2.4/ComposerVts.h index 83e74ed698..b094bc8028 100644 --- a/graphics/composer/2.4/utils/vts/include/composer-vts/2.4/ComposerVts.h +++ b/graphics/composer/2.4/utils/vts/include/composer-vts/2.4/ComposerVts.h @@ -84,6 +84,13 @@ class ComposerClient : public V2_3::vts::ComposerClient { const IComposerClient::VsyncPeriodChangeConstraints& vsyncPeriodChangeConstraints, VsyncPeriodChangeTimeline* timeline); + Error setAutoLowLatencyMode(Display display, bool on); + + Error getSupportedContentTypes( + Display display, std::vector* outSupportedContentTypes); + + Error setContentType(Display display, IComposerClient::ContentType contentType); + private: const sp mClient; }; diff --git a/graphics/composer/2.4/vts/functional/VtsHalGraphicsComposerV2_4TargetTest.cpp b/graphics/composer/2.4/vts/functional/VtsHalGraphicsComposerV2_4TargetTest.cpp index f038f551e3..6b6f2a5b5d 100644 --- a/graphics/composer/2.4/vts/functional/VtsHalGraphicsComposerV2_4TargetTest.cpp +++ b/graphics/composer/2.4/vts/functional/VtsHalGraphicsComposerV2_4TargetTest.cpp @@ -47,6 +47,9 @@ using common::V1_2::PixelFormat; using mapper::V2_0::IMapper; using mapper::V2_0::vts::Gralloc; +using ContentType = IComposerClient::ContentType; +using DisplayCapability = IComposerClient::DisplayCapability; + class GraphicsComposerHidlTest : public ::testing::TestWithParam { protected: void SetUp() override { @@ -117,6 +120,11 @@ class GraphicsComposerHidlTest : public ::testing::TestWithParam { void Test_setActiveConfigWithConstraints( const IComposerClient::VsyncPeriodChangeConstraints& constraints); + void Test_setContentType(const ContentType& contentType, const char* contentTypeStr); + void Test_setContentTypeForDisplay(const Display& display, + const std::vector& capabilities, + const ContentType& contentType, const char* contentTypeStr); + std::unique_ptr mComposer; std::unique_ptr mComposerClient; sp mComposerCallback; @@ -377,6 +385,117 @@ TEST_P(GraphicsComposerHidlTest, setActiveConfigWithConstraints_delayed) { Test_setActiveConfigWithConstraints(constraints); } +TEST_P(GraphicsComposerHidlTest, setAutoLowLatencyModeBadDisplay) { + EXPECT_EQ(Error::BAD_DISPLAY, mComposerClient->setAutoLowLatencyMode(mInvalidDisplayId, true)); + EXPECT_EQ(Error::BAD_DISPLAY, mComposerClient->setAutoLowLatencyMode(mInvalidDisplayId, false)); +} + +TEST_P(GraphicsComposerHidlTest, setAutoLowLatencyMode) { + for (Display display : mComposerCallback->getDisplays()) { + std::vector capabilities; + const auto error = mComposerClient->getDisplayCapabilities(display, &capabilities); + EXPECT_EQ(Error::NONE, error); + + const bool allmSupport = + std::find(capabilities.begin(), capabilities.end(), + DisplayCapability::AUTO_LOW_LATENCY_MODE) != capabilities.end(); + + if (!allmSupport) { + EXPECT_EQ(Error::UNSUPPORTED, + mComposerClient->setAutoLowLatencyMode(mPrimaryDisplay, true)); + EXPECT_EQ(Error::UNSUPPORTED, + mComposerClient->setAutoLowLatencyMode(mPrimaryDisplay, false)); + GTEST_SUCCEED() << "Auto Low Latency Mode is not supported on display " + << to_string(display) << ", skipping test"; + return; + } + + EXPECT_EQ(Error::NONE, mComposerClient->setAutoLowLatencyMode(mPrimaryDisplay, true)); + EXPECT_EQ(Error::NONE, mComposerClient->setAutoLowLatencyMode(mPrimaryDisplay, false)); + } +} + +TEST_P(GraphicsComposerHidlTest, getSupportedContentTypesBadDisplay) { + std::vector supportedContentTypes; + const auto error = + mComposerClient->getSupportedContentTypes(mInvalidDisplayId, &supportedContentTypes); + EXPECT_EQ(Error::BAD_DISPLAY, error); +} + +TEST_P(GraphicsComposerHidlTest, getSupportedContentTypes) { + std::vector supportedContentTypes; + for (Display display : mComposerCallback->getDisplays()) { + supportedContentTypes.clear(); + const auto error = + mComposerClient->getSupportedContentTypes(display, &supportedContentTypes); + const bool noneSupported = + std::find(supportedContentTypes.begin(), supportedContentTypes.end(), + ContentType::NONE) != supportedContentTypes.end(); + EXPECT_EQ(Error::NONE, error); + EXPECT_FALSE(noneSupported); + } +} + +TEST_P(GraphicsComposerHidlTest, setContentTypeNoneAlwaysAccepted) { + for (Display display : mComposerCallback->getDisplays()) { + const auto error = mComposerClient->setContentType(display, ContentType::NONE); + EXPECT_NE(Error::UNSUPPORTED, error); + } +} + +TEST_P(GraphicsComposerHidlTest, setContentTypeBadDisplay) { + const auto types = {ContentType::NONE, ContentType::GRAPHICS, ContentType::PHOTO, + ContentType::CINEMA, ContentType::GAME}; + for (auto type : types) { + EXPECT_EQ(Error::BAD_DISPLAY, mComposerClient->setContentType(mInvalidDisplayId, type)); + } +} + +void GraphicsComposerHidlTest::Test_setContentTypeForDisplay( + const Display& display, const std::vector& capabilities, + const ContentType& contentType, const char* contentTypeStr) { + const bool contentTypeSupport = + std::find(capabilities.begin(), capabilities.end(), contentType) != capabilities.end(); + + if (!contentTypeSupport) { + EXPECT_EQ(Error::UNSUPPORTED, mComposerClient->setContentType(display, contentType)); + GTEST_SUCCEED() << contentTypeStr << " content type is not supported on display " + << to_string(display) << ", skipping test"; + return; + } + + EXPECT_EQ(Error::NONE, mComposerClient->setContentType(display, contentType)); + EXPECT_EQ(Error::NONE, mComposerClient->setContentType(display, ContentType::NONE)); +} + +void GraphicsComposerHidlTest::Test_setContentType(const ContentType& contentType, + const char* contentTypeStr) { + for (Display display : mComposerCallback->getDisplays()) { + std::vector supportedContentTypes; + const auto error = + mComposerClient->getSupportedContentTypes(display, &supportedContentTypes); + EXPECT_EQ(Error::NONE, error); + + Test_setContentTypeForDisplay(display, supportedContentTypes, contentType, contentTypeStr); + } +} + +TEST_P(GraphicsComposerHidlTest, setGraphicsContentType) { + Test_setContentType(ContentType::GRAPHICS, "GRAPHICS"); +} + +TEST_P(GraphicsComposerHidlTest, setPhotoContentType) { + Test_setContentType(ContentType::PHOTO, "PHOTO"); +} + +TEST_P(GraphicsComposerHidlTest, setCinemaContentType) { + Test_setContentType(ContentType::CINEMA, "CINEMA"); +} + +TEST_P(GraphicsComposerHidlTest, setGameContentType) { + Test_setContentType(ContentType::GAME, "GAME"); +} + INSTANTIATE_TEST_SUITE_P( PerInstance, GraphicsComposerHidlTest, testing::ValuesIn(android::hardware::getAllHalInstanceNames(IComposer::descriptor)),