blob: e32c4bf145d2b529c4c512838ffb838fdad53d3b [file] [log] [blame]
/*
* Copyright 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#undef LOG_TAG
#define LOG_TAG "LibSurfaceFlingerUnittests"
#include "DisplayHardware/DisplayMode.h"
#include "DisplayTransactionTestHelpers.h"
namespace android {
namespace {
using hal::RenderIntent;
// For this variant, SurfaceFlinger should configure itself with wide display
// support, and the display should respond with an non-empty list of supported
// color modes. Wide-color support should be configured.
template <typename Display>
struct WideColorP3ColorimetricSupportedVariant {
static constexpr bool WIDE_COLOR_SUPPORTED = true;
static void injectConfigChange(DisplayTransactionTest* test) {
test->mFlinger.mutableUseColorManagement() = true;
test->mFlinger.mutableHasWideColorDisplay() = true;
test->mFlinger.mutableDisplayColorSetting() = DisplayColorSetting::kUnmanaged;
}
static void setupComposerCallExpectations(DisplayTransactionTest* test) {
EXPECT_CALL(*test->mNativeWindow, perform(NATIVE_WINDOW_SET_BUFFERS_DATASPACE)).Times(1);
EXPECT_CALL(*test->mComposer, getColorModes(Display::HWC_DISPLAY_ID, _))
.WillOnce(DoAll(SetArgPointee<1>(std::vector<ColorMode>({ColorMode::DISPLAY_P3})),
Return(Error::NONE)));
EXPECT_CALL(*test->mComposer,
getRenderIntents(Display::HWC_DISPLAY_ID, ColorMode::DISPLAY_P3, _))
.WillOnce(DoAll(SetArgPointee<2>(
std::vector<RenderIntent>({RenderIntent::COLORIMETRIC})),
Return(Error::NONE)));
EXPECT_CALL(*test->mComposer,
setColorMode(Display::HWC_DISPLAY_ID, ColorMode::SRGB,
RenderIntent::COLORIMETRIC))
.WillOnce(Return(Error::NONE));
}
};
template <typename Display>
struct Hdr10PlusSupportedVariant {
static constexpr bool HDR10_PLUS_SUPPORTED = true;
static constexpr bool HDR10_SUPPORTED = true;
static constexpr bool HDR_HLG_SUPPORTED = false;
static constexpr bool HDR_DOLBY_VISION_SUPPORTED = false;
static void setupComposerCallExpectations(DisplayTransactionTest* test) {
EXPECT_CALL(*test->mComposer, getHdrCapabilities(_, _, _, _, _))
.WillOnce(DoAll(SetArgPointee<1>(std::vector<Hdr>({
Hdr::HDR10_PLUS,
Hdr::HDR10,
})),
Return(Error::NONE)));
}
};
// For this variant, the composer should respond with a non-empty list of HDR
// modes containing HDR10, so HDR10 support should be configured.
template <typename Display>
struct Hdr10SupportedVariant {
static constexpr bool HDR10_PLUS_SUPPORTED = false;
static constexpr bool HDR10_SUPPORTED = true;
static constexpr bool HDR_HLG_SUPPORTED = false;
static constexpr bool HDR_DOLBY_VISION_SUPPORTED = false;
static void setupComposerCallExpectations(DisplayTransactionTest* test) {
EXPECT_CALL(*test->mComposer, getHdrCapabilities(Display::HWC_DISPLAY_ID, _, _, _, _))
.WillOnce(DoAll(SetArgPointee<1>(std::vector<Hdr>({Hdr::HDR10})),
Return(Error::NONE)));
}
};
// For this variant, the composer should respond with a non-empty list of HDR
// modes containing HLG, so HLG support should be configured.
template <typename Display>
struct HdrHlgSupportedVariant {
static constexpr bool HDR10_PLUS_SUPPORTED = false;
static constexpr bool HDR10_SUPPORTED = false;
static constexpr bool HDR_HLG_SUPPORTED = true;
static constexpr bool HDR_DOLBY_VISION_SUPPORTED = false;
static void setupComposerCallExpectations(DisplayTransactionTest* test) {
EXPECT_CALL(*test->mComposer, getHdrCapabilities(Display::HWC_DISPLAY_ID, _, _, _, _))
.WillOnce(
DoAll(SetArgPointee<1>(std::vector<Hdr>({Hdr::HLG})), Return(Error::NONE)));
}
};
// For this variant, the composer should respond with a non-empty list of HDR
// modes containing DOLBY_VISION, so DOLBY_VISION support should be configured.
template <typename Display>
struct HdrDolbyVisionSupportedVariant {
static constexpr bool HDR10_PLUS_SUPPORTED = false;
static constexpr bool HDR10_SUPPORTED = false;
static constexpr bool HDR_HLG_SUPPORTED = false;
static constexpr bool HDR_DOLBY_VISION_SUPPORTED = true;
static void setupComposerCallExpectations(DisplayTransactionTest* test) {
EXPECT_CALL(*test->mComposer, getHdrCapabilities(Display::HWC_DISPLAY_ID, _, _, _, _))
.WillOnce(DoAll(SetArgPointee<1>(std::vector<Hdr>({Hdr::DOLBY_VISION})),
Return(Error::NONE)));
}
};
template <typename Display>
struct Smpte2086PerFrameMetadataSupportVariant {
static constexpr int PER_FRAME_METADATA_KEYS = HdrMetadata::Type::SMPTE2086;
static void setupComposerCallExpectations(DisplayTransactionTest* test) {
EXPECT_CALL(*test->mComposer, getPerFrameMetadataKeys(Display::HWC_DISPLAY_ID))
.WillOnce(Return(std::vector<PerFrameMetadataKey>({
PerFrameMetadataKey::DISPLAY_RED_PRIMARY_X,
PerFrameMetadataKey::DISPLAY_RED_PRIMARY_Y,
PerFrameMetadataKey::DISPLAY_GREEN_PRIMARY_X,
PerFrameMetadataKey::DISPLAY_GREEN_PRIMARY_Y,
PerFrameMetadataKey::DISPLAY_BLUE_PRIMARY_X,
PerFrameMetadataKey::DISPLAY_BLUE_PRIMARY_Y,
PerFrameMetadataKey::WHITE_POINT_X,
PerFrameMetadataKey::WHITE_POINT_Y,
PerFrameMetadataKey::MAX_LUMINANCE,
PerFrameMetadataKey::MIN_LUMINANCE,
})));
}
};
template <typename Display>
struct Cta861_3_PerFrameMetadataSupportVariant {
static constexpr int PER_FRAME_METADATA_KEYS = HdrMetadata::Type::CTA861_3;
static void setupComposerCallExpectations(DisplayTransactionTest* test) {
EXPECT_CALL(*test->mComposer, getPerFrameMetadataKeys(Display::HWC_DISPLAY_ID))
.WillOnce(Return(std::vector<PerFrameMetadataKey>({
PerFrameMetadataKey::MAX_CONTENT_LIGHT_LEVEL,
PerFrameMetadataKey::MAX_FRAME_AVERAGE_LIGHT_LEVEL,
})));
}
};
template <typename Display>
struct Hdr10_Plus_PerFrameMetadataSupportVariant {
static constexpr int PER_FRAME_METADATA_KEYS = HdrMetadata::Type::HDR10PLUS;
static void setupComposerCallExpectations(DisplayTransactionTest* test) {
EXPECT_CALL(*test->mComposer, getPerFrameMetadataKeys(Display::HWC_DISPLAY_ID))
.WillOnce(Return(std::vector<PerFrameMetadataKey>({
PerFrameMetadataKey::HDR10_PLUS_SEI,
})));
}
};
using WideColorP3ColorimetricDisplayCase =
Case<PrimaryDisplayVariant, WideColorP3ColorimetricSupportedVariant<PrimaryDisplayVariant>,
HdrNotSupportedVariant<PrimaryDisplayVariant>,
NoPerFrameMetadataSupportVariant<PrimaryDisplayVariant>>;
using Hdr10PlusDisplayCase =
Case<PrimaryDisplayVariant, WideColorNotSupportedVariant<PrimaryDisplayVariant>,
Hdr10SupportedVariant<PrimaryDisplayVariant>,
Hdr10_Plus_PerFrameMetadataSupportVariant<PrimaryDisplayVariant>>;
using Hdr10DisplayCase =
Case<PrimaryDisplayVariant, WideColorNotSupportedVariant<PrimaryDisplayVariant>,
Hdr10SupportedVariant<PrimaryDisplayVariant>,
NoPerFrameMetadataSupportVariant<PrimaryDisplayVariant>>;
using HdrHlgDisplayCase =
Case<PrimaryDisplayVariant, WideColorNotSupportedVariant<PrimaryDisplayVariant>,
HdrHlgSupportedVariant<PrimaryDisplayVariant>,
NoPerFrameMetadataSupportVariant<PrimaryDisplayVariant>>;
using HdrDolbyVisionDisplayCase =
Case<PrimaryDisplayVariant, WideColorNotSupportedVariant<PrimaryDisplayVariant>,
HdrDolbyVisionSupportedVariant<PrimaryDisplayVariant>,
NoPerFrameMetadataSupportVariant<PrimaryDisplayVariant>>;
using HdrSmpte2086DisplayCase =
Case<PrimaryDisplayVariant, WideColorNotSupportedVariant<PrimaryDisplayVariant>,
HdrNotSupportedVariant<PrimaryDisplayVariant>,
Smpte2086PerFrameMetadataSupportVariant<PrimaryDisplayVariant>>;
using HdrCta861_3_DisplayCase =
Case<PrimaryDisplayVariant, WideColorNotSupportedVariant<PrimaryDisplayVariant>,
HdrNotSupportedVariant<PrimaryDisplayVariant>,
Cta861_3_PerFrameMetadataSupportVariant<PrimaryDisplayVariant>>;
class SetupNewDisplayDeviceInternalTest : public DisplayTransactionTest {
public:
template <typename T>
void setupNewDisplayDeviceInternalTest();
};
template <typename Case>
void SetupNewDisplayDeviceInternalTest::setupNewDisplayDeviceInternalTest() {
const sp<BBinder> displayToken = new BBinder();
const sp<compositionengine::mock::DisplaySurface> displaySurface =
new compositionengine::mock::DisplaySurface();
const sp<mock::GraphicBufferProducer> producer = new mock::GraphicBufferProducer();
// --------------------------------------------------------------------
// Preconditions
// Wide color displays support is configured appropriately
Case::WideColorSupport::injectConfigChange(this);
// The display is setup with the HWC.
Case::Display::injectHwcDisplay(this);
// SurfaceFlinger will use a test-controlled factory for native window
// surfaces.
injectFakeNativeWindowSurfaceFactory();
// A compositionengine::Display has already been created
auto compositionDisplay = Case::Display::injectCompositionDisplay(this);
// --------------------------------------------------------------------
// Call Expectations
// Various native window calls will be made.
Case::Display::setupNativeWindowSurfaceCreationCallExpectations(this);
Case::Display::setupHwcGetActiveConfigCallExpectations(this);
Case::Display::setupHwcGetConfigsCallExpectations(this);
Case::WideColorSupport::setupComposerCallExpectations(this);
Case::HdrSupport::setupComposerCallExpectations(this);
Case::PerFrameMetadataSupport::setupComposerCallExpectations(this);
// --------------------------------------------------------------------
// Invocation
DisplayDeviceState state;
if constexpr (constexpr auto connectionType = Case::Display::CONNECTION_TYPE::value) {
const auto displayId = PhysicalDisplayId::tryCast(Case::Display::DISPLAY_ID::get());
ASSERT_TRUE(displayId);
const auto hwcDisplayId = Case::Display::HWC_DISPLAY_ID_OPT::value;
ASSERT_TRUE(hwcDisplayId);
mFlinger.getHwComposer().allocatePhysicalDisplay(*hwcDisplayId, *displayId);
DisplayModePtr activeMode = DisplayMode::Builder(Case::Display::HWC_ACTIVE_CONFIG_ID)
.setWidth(Case::Display::WIDTH)
.setHeight(Case::Display::HEIGHT)
.setVsyncPeriod(DEFAULT_VSYNC_PERIOD)
.setDpiX(DEFAULT_DPI)
.setDpiY(DEFAULT_DPI)
.setGroup(0)
.build();
DisplayModes modes{activeMode};
state.physical = {.id = *displayId,
.type = *connectionType,
.hwcDisplayId = *hwcDisplayId,
.supportedModes = modes,
.activeMode = activeMode};
}
state.isSecure = static_cast<bool>(Case::Display::SECURE);
auto device = mFlinger.setupNewDisplayDeviceInternal(displayToken, compositionDisplay, state,
displaySurface, producer);
// --------------------------------------------------------------------
// Postconditions
ASSERT_TRUE(device != nullptr);
EXPECT_EQ(Case::Display::DISPLAY_ID::get(), device->getId());
EXPECT_EQ(Case::Display::CONNECTION_TYPE::value, device->getConnectionType());
EXPECT_EQ(static_cast<bool>(Case::Display::VIRTUAL), device->isVirtual());
EXPECT_EQ(static_cast<bool>(Case::Display::SECURE), device->isSecure());
EXPECT_EQ(static_cast<bool>(Case::Display::PRIMARY), device->isPrimary());
EXPECT_EQ(Case::Display::WIDTH, device->getWidth());
EXPECT_EQ(Case::Display::HEIGHT, device->getHeight());
EXPECT_EQ(Case::WideColorSupport::WIDE_COLOR_SUPPORTED, device->hasWideColorGamut());
EXPECT_EQ(Case::HdrSupport::HDR10_PLUS_SUPPORTED, device->hasHDR10PlusSupport());
EXPECT_EQ(Case::HdrSupport::HDR10_SUPPORTED, device->hasHDR10Support());
EXPECT_EQ(Case::HdrSupport::HDR_HLG_SUPPORTED, device->hasHLGSupport());
EXPECT_EQ(Case::HdrSupport::HDR_DOLBY_VISION_SUPPORTED, device->hasDolbyVisionSupport());
EXPECT_EQ(Case::PerFrameMetadataSupport::PER_FRAME_METADATA_KEYS,
device->getSupportedPerFrameMetadata());
if constexpr (Case::Display::CONNECTION_TYPE::value) {
EXPECT_EQ(1, device->getSupportedModes().size());
EXPECT_NE(nullptr, device->getActiveMode());
EXPECT_EQ(Case::Display::HWC_ACTIVE_CONFIG_ID, device->getActiveMode()->getHwcId());
}
}
TEST_F(SetupNewDisplayDeviceInternalTest, createSimplePrimaryDisplay) {
setupNewDisplayDeviceInternalTest<SimplePrimaryDisplayCase>();
}
TEST_F(SetupNewDisplayDeviceInternalTest, createSimpleExternalDisplay) {
setupNewDisplayDeviceInternalTest<SimpleExternalDisplayCase>();
}
TEST_F(SetupNewDisplayDeviceInternalTest, createNonHwcVirtualDisplay) {
setupNewDisplayDeviceInternalTest<NonHwcVirtualDisplayCase>();
}
TEST_F(SetupNewDisplayDeviceInternalTest, createHwcVirtualDisplay) {
setupNewDisplayDeviceInternalTest<HwcVirtualDisplayCase>();
}
TEST_F(SetupNewDisplayDeviceInternalTest, createWideColorP3Display) {
setupNewDisplayDeviceInternalTest<WideColorP3ColorimetricDisplayCase>();
}
TEST_F(SetupNewDisplayDeviceInternalTest, createHdr10PlusDisplay) {
setupNewDisplayDeviceInternalTest<Hdr10PlusDisplayCase>();
}
TEST_F(SetupNewDisplayDeviceInternalTest, createHdr10Display) {
setupNewDisplayDeviceInternalTest<Hdr10DisplayCase>();
}
TEST_F(SetupNewDisplayDeviceInternalTest, createHdrHlgDisplay) {
setupNewDisplayDeviceInternalTest<HdrHlgDisplayCase>();
}
TEST_F(SetupNewDisplayDeviceInternalTest, createHdrDolbyVisionDisplay) {
setupNewDisplayDeviceInternalTest<HdrDolbyVisionDisplayCase>();
}
TEST_F(SetupNewDisplayDeviceInternalTest, createHdrSmpte2086DisplayCase) {
setupNewDisplayDeviceInternalTest<HdrSmpte2086DisplayCase>();
}
TEST_F(SetupNewDisplayDeviceInternalTest, createHdrCta816_3_DisplayCase) {
setupNewDisplayDeviceInternalTest<HdrCta861_3_DisplayCase>();
}
} // namespace
} // namespace android