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
This commit is contained in:
parent
977c50bc91
commit
2bd7d43325
7 changed files with 301 additions and 0 deletions
|
@ -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<ContentType> 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);
|
||||
};
|
||||
|
|
|
@ -139,6 +139,24 @@ class ComposerClientImpl : public V2_3::hal::detail::ComposerClientImpl<Interfac
|
|||
return Void();
|
||||
}
|
||||
|
||||
Return<Error> setAutoLowLatencyMode(Display display, bool on) override {
|
||||
return mHal->setAutoLowLatencyMode(display, on);
|
||||
}
|
||||
|
||||
Return<void> getSupportedContentTypes(
|
||||
Display display, IComposerClient::getSupportedContentTypes_cb hidl_cb) override {
|
||||
std::vector<IComposerClient::ContentType> supportedContentTypes;
|
||||
Error error = mHal->getSupportedContentTypes(display, &supportedContentTypes);
|
||||
|
||||
hidl_cb(error, supportedContentTypes);
|
||||
return Void();
|
||||
}
|
||||
|
||||
Return<Error> setContentType(Display display,
|
||||
IComposerClient::ContentType contentType) override {
|
||||
return mHal->setContentType(display, contentType);
|
||||
}
|
||||
|
||||
static std::unique_ptr<ComposerClientImpl> create(Hal* hal) {
|
||||
auto client = std::make_unique<ComposerClientImpl>(hal);
|
||||
return client->init() ? std::move(client) : nullptr;
|
||||
|
|
|
@ -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<IComposerClient::ContentType>* outSupportedContentTypes) = 0;
|
||||
virtual Error setContentType(Display display, IComposerClient::ContentType contentType) = 0;
|
||||
};
|
||||
|
||||
} // namespace hal
|
||||
|
|
|
@ -167,6 +167,57 @@ class HwcHalImpl : public V2_3::passthrough::detail::HwcHalImpl<Hal> {
|
|||
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>(error);
|
||||
}
|
||||
return Error::NONE;
|
||||
}
|
||||
|
||||
Error getSupportedContentTypes(
|
||||
Display display,
|
||||
std::vector<IComposerClient::ContentType>* 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>(error);
|
||||
}
|
||||
|
||||
outSupportedContentTypes->resize(count);
|
||||
|
||||
error = mDispatch.getSupportedContentTypes(
|
||||
mDevice, display, &count,
|
||||
reinterpret_cast<std::underlying_type<IComposerClient::ContentType>::type*>(
|
||||
outSupportedContentTypes->data()));
|
||||
if (error != HWC2_ERROR_NONE) {
|
||||
*outSupportedContentTypes = std::vector<IComposerClient::ContentType>();
|
||||
return static_cast<Error>(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<int32_t>(contentType));
|
||||
if (error != HWC2_ERROR_NONE) {
|
||||
return static_cast<Error>(error);
|
||||
}
|
||||
return Error::NONE;
|
||||
}
|
||||
|
||||
protected:
|
||||
bool initDispatch() override {
|
||||
if (!BaseType2_3::initDispatch()) {
|
||||
|
@ -179,6 +230,11 @@ class HwcHalImpl : public V2_3::passthrough::detail::HwcHalImpl<Hal> {
|
|||
&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<Hal> {
|
|||
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;
|
||||
|
|
|
@ -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<IComposerClient::ContentType>* 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
|
||||
|
|
|
@ -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<IComposerClient::ContentType>* outSupportedContentTypes);
|
||||
|
||||
Error setContentType(Display display, IComposerClient::ContentType contentType);
|
||||
|
||||
private:
|
||||
const sp<IComposerClient> mClient;
|
||||
};
|
||||
|
|
|
@ -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<std::string> {
|
||||
protected:
|
||||
void SetUp() override {
|
||||
|
@ -117,6 +120,11 @@ class GraphicsComposerHidlTest : public ::testing::TestWithParam<std::string> {
|
|||
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<ContentType>& capabilities,
|
||||
const ContentType& contentType, const char* contentTypeStr);
|
||||
|
||||
std::unique_ptr<Composer> mComposer;
|
||||
std::unique_ptr<ComposerClient> mComposerClient;
|
||||
sp<V2_1::vts::GraphicsComposerCallback> 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<DisplayCapability> 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<ContentType> supportedContentTypes;
|
||||
const auto error =
|
||||
mComposerClient->getSupportedContentTypes(mInvalidDisplayId, &supportedContentTypes);
|
||||
EXPECT_EQ(Error::BAD_DISPLAY, error);
|
||||
}
|
||||
|
||||
TEST_P(GraphicsComposerHidlTest, getSupportedContentTypes) {
|
||||
std::vector<ContentType> 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<ContentType>& 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<ContentType> 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)),
|
||||
|
|
Loading…
Reference in a new issue