| /** |
| * Copyright (c) 2021, 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. |
| */ |
| |
| #define LOG_TAG "graphics_composer_aidl_hal_readback_tests@3" |
| |
| #include <aidl/Gtest.h> |
| #include <aidl/Vintf.h> |
| #include <aidl/android/hardware/graphics/common/BufferUsage.h> |
| #include <aidl/android/hardware/graphics/composer3/IComposer.h> |
| #include <gtest/gtest.h> |
| #include <ui/DisplayId.h> |
| #include <ui/DisplayIdentification.h> |
| #include <ui/GraphicBuffer.h> |
| #include <ui/PixelFormat.h> |
| #include <ui/Rect.h> |
| #include "GraphicsComposerCallback.h" |
| #include "ReadbackVts.h" |
| #include "RenderEngineVts.h" |
| #include "VtsComposerClient.h" |
| |
| namespace aidl::android::hardware::graphics::composer3::vts { |
| namespace { |
| |
| using ::android::Rect; |
| using common::Dataspace; |
| using common::PixelFormat; |
| |
| class GraphicsCompositionTestBase : public ::testing::Test { |
| protected: |
| void SetUpBase(const std::string& name) { |
| mComposerClient = std::make_shared<VtsComposerClient>(name); |
| ASSERT_TRUE(mComposerClient->createClient().isOk()); |
| |
| const auto& [status, displays] = mComposerClient->getDisplays(); |
| ASSERT_TRUE(status.isOk()); |
| mDisplays = displays; |
| mWriter.reset(new ComposerClientWriter(getPrimaryDisplayId())); |
| |
| setTestColorModes(); |
| |
| // explicitly disable vsync |
| for (const auto& display : mDisplays) { |
| EXPECT_TRUE(mComposerClient->setVsync(display.getDisplayId(), /*enable*/ false).isOk()); |
| } |
| mComposerClient->setVsyncAllowed(/*isAllowed*/ false); |
| |
| EXPECT_TRUE(mComposerClient->setPowerMode(getPrimaryDisplayId(), PowerMode::ON).isOk()); |
| |
| const auto format = getHasReadbackBuffer() ? mPixelFormat : common::PixelFormat::RGBA_8888; |
| |
| ASSERT_NO_FATAL_FAILURE( |
| mTestRenderEngine = std::unique_ptr<TestRenderEngine>(new TestRenderEngine( |
| ::android::renderengine::RenderEngineCreationArgs::Builder() |
| .setPixelFormat(static_cast<int>(format)) |
| .setImageCacheSize(TestRenderEngine::sMaxFrameBufferAcquireBuffers) |
| .setEnableProtectedContext(false) |
| .setPrecacheToneMapperShaderOnly(false) |
| .setContextPriority(::android::renderengine::RenderEngine:: |
| ContextPriority::HIGH) |
| .build()))); |
| |
| mClientCompositionDisplaySettings.physicalDisplay = |
| Rect(getDisplayWidth(), getDisplayHeight()); |
| mClientCompositionDisplaySettings.clip = mClientCompositionDisplaySettings.physicalDisplay; |
| |
| mTestRenderEngine->initGraphicBuffer( |
| static_cast<uint32_t>(getDisplayWidth()), static_cast<uint32_t>(getDisplayHeight()), |
| /*layerCount*/ 1U, |
| static_cast<uint64_t>( |
| static_cast<uint64_t>(common::BufferUsage::CPU_READ_OFTEN) | |
| static_cast<uint64_t>(common::BufferUsage::CPU_WRITE_OFTEN) | |
| static_cast<uint64_t>(common::BufferUsage::GPU_RENDER_TARGET))); |
| mTestRenderEngine->setDisplaySettings(mClientCompositionDisplaySettings); |
| } |
| |
| void TearDown() override { |
| ASSERT_FALSE(mDisplays.empty()); |
| ASSERT_TRUE(mComposerClient->setPowerMode(getPrimaryDisplayId(), PowerMode::OFF).isOk()); |
| ASSERT_TRUE(mComposerClient->tearDown(mWriter.get())); |
| mComposerClient.reset(); |
| const auto errors = mReader.takeErrors(); |
| ASSERT_TRUE(mReader.takeErrors().empty()); |
| ASSERT_TRUE(mReader.takeChangedCompositionTypes(getPrimaryDisplayId()).empty()); |
| } |
| |
| const VtsDisplay& getPrimaryDisplay() const { return mDisplays[0]; } |
| |
| int64_t getPrimaryDisplayId() const { return getPrimaryDisplay().getDisplayId(); } |
| |
| int64_t getInvalidDisplayId() const { return mComposerClient->getInvalidDisplayId(); } |
| |
| int32_t getDisplayWidth() const { return getPrimaryDisplay().getDisplayWidth(); } |
| |
| int32_t getDisplayHeight() const { return getPrimaryDisplay().getDisplayHeight(); } |
| |
| void assertServiceSpecificError(const ScopedAStatus& status, int32_t serviceSpecificError) { |
| ASSERT_EQ(status.getExceptionCode(), EX_SERVICE_SPECIFIC); |
| ASSERT_EQ(status.getServiceSpecificError(), serviceSpecificError); |
| } |
| |
| std::pair<bool, ::android::sp<::android::GraphicBuffer>> allocateBuffer(uint32_t usage) { |
| const auto width = static_cast<uint32_t>(getDisplayWidth()); |
| const auto height = static_cast<uint32_t>(getDisplayHeight()); |
| |
| const auto& graphicBuffer = ::android::sp<::android::GraphicBuffer>::make( |
| width, height, ::android::PIXEL_FORMAT_RGBA_8888, |
| /*layerCount*/ 1u, usage, "VtsHalGraphicsComposer3_ReadbackTest"); |
| |
| if (graphicBuffer && ::android::OK == graphicBuffer->initCheck()) { |
| return {true, graphicBuffer}; |
| } |
| return {false, graphicBuffer}; |
| } |
| |
| void writeLayers(const std::vector<std::shared_ptr<TestLayer>>& layers) { |
| for (const auto& layer : layers) { |
| layer->write(*mWriter); |
| } |
| execute(); |
| } |
| |
| void execute() { |
| auto commands = mWriter->takePendingCommands(); |
| if (commands.empty()) { |
| return; |
| } |
| |
| auto [status, results] = mComposerClient->executeCommands(commands); |
| ASSERT_TRUE(status.isOk()) << "executeCommands failed " << status.getDescription(); |
| |
| mReader.parse(std::move(results)); |
| } |
| |
| bool getHasReadbackBuffer() { |
| auto [status, readBackBufferAttributes] = |
| mComposerClient->getReadbackBufferAttributes(getPrimaryDisplayId()); |
| if (status.isOk()) { |
| mPixelFormat = readBackBufferAttributes.format; |
| mDataspace = readBackBufferAttributes.dataspace; |
| return ReadbackHelper::readbackSupported(mPixelFormat, mDataspace); |
| } |
| EXPECT_NO_FATAL_FAILURE( |
| assertServiceSpecificError(status, IComposerClient::EX_UNSUPPORTED)); |
| return false; |
| } |
| |
| std::shared_ptr<VtsComposerClient> mComposerClient; |
| std::vector<VtsDisplay> mDisplays; |
| // use the slot count usually set by SF |
| std::vector<ColorMode> mTestColorModes; |
| std::unique_ptr<ComposerClientWriter> mWriter; |
| ComposerClientReader mReader; |
| std::unique_ptr<TestRenderEngine> mTestRenderEngine; |
| common::PixelFormat mPixelFormat; |
| common::Dataspace mDataspace; |
| ::android::renderengine::DisplaySettings mClientCompositionDisplaySettings; |
| |
| static constexpr uint32_t kClientTargetSlotCount = 64; |
| |
| private: |
| void setTestColorModes() { |
| mTestColorModes.clear(); |
| const auto& [status, modes] = mComposerClient->getColorModes(getPrimaryDisplayId()); |
| ASSERT_TRUE(status.isOk()); |
| |
| for (ColorMode mode : modes) { |
| if (std::find(ReadbackHelper::colorModes.begin(), ReadbackHelper::colorModes.end(), |
| mode) != ReadbackHelper::colorModes.end()) { |
| mTestColorModes.push_back(mode); |
| } |
| } |
| } |
| }; |
| |
| class GraphicsCompositionTest : public GraphicsCompositionTestBase, |
| public testing::WithParamInterface<std::string> { |
| public: |
| void SetUp() override { SetUpBase(GetParam()); } |
| }; |
| |
| TEST_P(GraphicsCompositionTest, SingleSolidColorLayer) { |
| for (ColorMode mode : mTestColorModes) { |
| EXPECT_TRUE(mComposerClient |
| ->setColorMode(getPrimaryDisplayId(), mode, RenderIntent::COLORIMETRIC) |
| .isOk()); |
| |
| bool isSupported; |
| ASSERT_NO_FATAL_FAILURE(isSupported = getHasReadbackBuffer()); |
| if (!isSupported) { |
| GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace"; |
| return; |
| } |
| |
| auto layer = |
| std::make_shared<TestColorLayer>(mComposerClient, getPrimaryDisplayId(), *mWriter); |
| common::Rect coloredSquare({0, 0, getDisplayWidth(), getDisplayHeight()}); |
| layer->setColor(BLUE); |
| layer->setDisplayFrame(coloredSquare); |
| layer->setZOrder(10); |
| |
| std::vector<std::shared_ptr<TestLayer>> layers = {layer}; |
| |
| // expected color for each pixel |
| std::vector<Color> expectedColors( |
| static_cast<size_t>(getDisplayWidth() * getDisplayHeight())); |
| ReadbackHelper::fillColorsArea(expectedColors, getDisplayWidth(), coloredSquare, BLUE); |
| |
| ReadbackBuffer readbackBuffer(getPrimaryDisplayId(), mComposerClient, getDisplayWidth(), |
| getDisplayHeight(), mPixelFormat, mDataspace); |
| ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer()); |
| |
| writeLayers(layers); |
| ASSERT_TRUE(mReader.takeErrors().empty()); |
| mWriter->validateDisplay(getPrimaryDisplayId(), ComposerClientWriter::kNoTimestamp, |
| VtsComposerClient::kNoFrameIntervalNs); |
| execute(); |
| // if hwc cannot handle and asks for composition change, |
| // just succeed the test |
| if (!mReader.takeChangedCompositionTypes(getPrimaryDisplayId()).empty()) { |
| GTEST_SUCCEED(); |
| return; |
| } |
| ASSERT_TRUE(mReader.takeErrors().empty()); |
| mWriter->presentDisplay(getPrimaryDisplayId()); |
| execute(); |
| ASSERT_TRUE(mReader.takeErrors().empty()); |
| |
| ASSERT_NO_FATAL_FAILURE(readbackBuffer.checkReadbackBuffer(expectedColors)); |
| mTestRenderEngine->setRenderLayers(layers); |
| ASSERT_NO_FATAL_FAILURE(mTestRenderEngine->drawLayers()); |
| ASSERT_NO_FATAL_FAILURE(mTestRenderEngine->checkColorBuffer(expectedColors)); |
| } |
| } |
| |
| TEST_P(GraphicsCompositionTest, SetLayerBuffer) { |
| for (ColorMode mode : mTestColorModes) { |
| EXPECT_TRUE(mComposerClient |
| ->setColorMode(getPrimaryDisplayId(), mode, RenderIntent::COLORIMETRIC) |
| .isOk()); |
| |
| bool isSupported; |
| ASSERT_NO_FATAL_FAILURE(isSupported = getHasReadbackBuffer()); |
| if (!isSupported) { |
| GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace"; |
| return; |
| } |
| |
| ReadbackBuffer readbackBuffer(getPrimaryDisplayId(), mComposerClient, getDisplayWidth(), |
| getDisplayHeight(), mPixelFormat, mDataspace); |
| ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer()); |
| std::vector<Color> expectedColors( |
| static_cast<size_t>(getDisplayWidth() * getDisplayHeight())); |
| ReadbackHelper::fillColorsArea(expectedColors, getDisplayWidth(), |
| {0, 0, getDisplayWidth(), getDisplayHeight() / 4}, RED); |
| ReadbackHelper::fillColorsArea( |
| expectedColors, getDisplayWidth(), |
| {0, getDisplayHeight() / 4, getDisplayWidth(), getDisplayHeight() / 2}, GREEN); |
| ReadbackHelper::fillColorsArea( |
| expectedColors, getDisplayWidth(), |
| {0, getDisplayHeight() / 2, getDisplayWidth(), getDisplayHeight()}, BLUE); |
| |
| auto layer = std::make_shared<TestBufferLayer>( |
| mComposerClient, *mTestRenderEngine, getPrimaryDisplayId(), getDisplayWidth(), |
| getDisplayHeight(), common::PixelFormat::RGBA_8888, *mWriter); |
| layer->setDisplayFrame({0, 0, getDisplayWidth(), getDisplayHeight()}); |
| layer->setZOrder(10); |
| layer->setDataspace(ReadbackHelper::getDataspaceForColorMode(mode)); |
| ASSERT_NO_FATAL_FAILURE(layer->setBuffer(expectedColors)); |
| |
| std::vector<std::shared_ptr<TestLayer>> layers = {layer}; |
| |
| writeLayers(layers); |
| ASSERT_TRUE(mReader.takeErrors().empty()); |
| mWriter->validateDisplay(getPrimaryDisplayId(), ComposerClientWriter::kNoTimestamp, |
| VtsComposerClient::kNoFrameIntervalNs); |
| execute(); |
| |
| if (!mReader.takeChangedCompositionTypes(getPrimaryDisplayId()).empty()) { |
| GTEST_SUCCEED(); |
| return; |
| } |
| ASSERT_TRUE(mReader.takeErrors().empty()); |
| |
| mWriter->presentDisplay(getPrimaryDisplayId()); |
| execute(); |
| |
| ASSERT_TRUE(mReader.takeErrors().empty()); |
| |
| ASSERT_NO_FATAL_FAILURE(readbackBuffer.checkReadbackBuffer(expectedColors)); |
| mTestRenderEngine->setRenderLayers(layers); |
| ASSERT_NO_FATAL_FAILURE(mTestRenderEngine->drawLayers()); |
| ASSERT_NO_FATAL_FAILURE(mTestRenderEngine->checkColorBuffer(expectedColors)); |
| } |
| } |
| |
| TEST_P(GraphicsCompositionTest, SetLayerBufferNoEffect) { |
| for (ColorMode mode : mTestColorModes) { |
| EXPECT_TRUE(mComposerClient |
| ->setColorMode(getPrimaryDisplayId(), mode, RenderIntent::COLORIMETRIC) |
| .isOk()); |
| |
| bool isSupported; |
| ASSERT_NO_FATAL_FAILURE(isSupported = getHasReadbackBuffer()); |
| if (!isSupported) { |
| GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace"; |
| return; |
| } |
| |
| auto layer = |
| std::make_shared<TestColorLayer>(mComposerClient, getPrimaryDisplayId(), *mWriter); |
| common::Rect coloredSquare({0, 0, getDisplayWidth(), getDisplayHeight()}); |
| layer->setColor(BLUE); |
| layer->setDisplayFrame(coloredSquare); |
| layer->setZOrder(10); |
| layer->write(*mWriter); |
| |
| // This following buffer call should have no effect |
| const auto usage = static_cast<uint32_t>(common::BufferUsage::CPU_WRITE_OFTEN) | |
| static_cast<uint32_t>(common::BufferUsage::CPU_READ_OFTEN); |
| const auto& [graphicBufferStatus, graphicBuffer] = allocateBuffer(usage); |
| ASSERT_TRUE(graphicBufferStatus); |
| const auto& buffer = graphicBuffer->handle; |
| mWriter->setLayerBuffer(getPrimaryDisplayId(), layer->getLayer(), /*slot*/ 0, buffer, |
| /*acquireFence*/ -1); |
| |
| // expected color for each pixel |
| std::vector<Color> expectedColors( |
| static_cast<size_t>(getDisplayWidth() * getDisplayHeight())); |
| ReadbackHelper::fillColorsArea(expectedColors, getDisplayWidth(), coloredSquare, BLUE); |
| |
| ReadbackBuffer readbackBuffer(getPrimaryDisplayId(), mComposerClient, getDisplayWidth(), |
| getDisplayHeight(), mPixelFormat, mDataspace); |
| ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer()); |
| |
| mWriter->validateDisplay(getPrimaryDisplayId(), ComposerClientWriter::kNoTimestamp, |
| VtsComposerClient::kNoFrameIntervalNs); |
| execute(); |
| |
| if (!mReader.takeChangedCompositionTypes(getPrimaryDisplayId()).empty()) { |
| GTEST_SUCCEED(); |
| return; |
| } |
| ASSERT_TRUE(mReader.takeErrors().empty()); |
| mWriter->presentDisplay(getPrimaryDisplayId()); |
| execute(); |
| ASSERT_TRUE(mReader.takeErrors().empty()); |
| |
| ASSERT_NO_FATAL_FAILURE(readbackBuffer.checkReadbackBuffer(expectedColors)); |
| } |
| } |
| |
| TEST_P(GraphicsCompositionTest, SetReadbackBuffer) { |
| bool isSupported; |
| ASSERT_NO_FATAL_FAILURE(isSupported = getHasReadbackBuffer()); |
| if (!isSupported) { |
| GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace"; |
| return; |
| } |
| |
| ReadbackBuffer readbackBuffer(getPrimaryDisplayId(), mComposerClient, getDisplayWidth(), |
| getDisplayHeight(), mPixelFormat, mDataspace); |
| |
| ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer()); |
| } |
| |
| TEST_P(GraphicsCompositionTest, SetReadbackBuffer_BadDisplay) { |
| bool isSupported; |
| ASSERT_NO_FATAL_FAILURE(isSupported = getHasReadbackBuffer()); |
| if (!isSupported) { |
| GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace"; |
| return; |
| } |
| |
| const auto usage = static_cast<uint32_t>(common::BufferUsage::CPU_WRITE_OFTEN) | |
| static_cast<uint32_t>(common::BufferUsage::CPU_READ_OFTEN); |
| const auto& [graphicBufferStatus, graphicBuffer] = allocateBuffer(usage); |
| ASSERT_TRUE(graphicBufferStatus); |
| const auto& bufferHandle = graphicBuffer->handle; |
| ::ndk::ScopedFileDescriptor fence = ::ndk::ScopedFileDescriptor(-1); |
| |
| const auto status = |
| mComposerClient->setReadbackBuffer(getInvalidDisplayId(), bufferHandle, fence); |
| |
| EXPECT_FALSE(status.isOk()); |
| EXPECT_NO_FATAL_FAILURE(assertServiceSpecificError(status, IComposerClient::EX_BAD_DISPLAY)); |
| } |
| |
| TEST_P(GraphicsCompositionTest, SetReadbackBuffer_BadParameter) { |
| bool isSupported; |
| ASSERT_NO_FATAL_FAILURE(isSupported = getHasReadbackBuffer()); |
| if (!isSupported) { |
| GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace"; |
| return; |
| } |
| |
| const native_handle_t bufferHandle{}; |
| ndk::ScopedFileDescriptor releaseFence = ndk::ScopedFileDescriptor(-1); |
| const auto status = |
| mComposerClient->setReadbackBuffer(getPrimaryDisplayId(), &bufferHandle, releaseFence); |
| |
| EXPECT_FALSE(status.isOk()); |
| EXPECT_NO_FATAL_FAILURE(assertServiceSpecificError(status, IComposerClient::EX_BAD_PARAMETER)); |
| } |
| |
| TEST_P(GraphicsCompositionTest, GetReadbackBufferFenceInactive) { |
| bool isSupported; |
| ASSERT_NO_FATAL_FAILURE(isSupported = getHasReadbackBuffer()); |
| if (!isSupported) { |
| GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace"; |
| return; |
| } |
| |
| const auto& [status, releaseFence] = |
| mComposerClient->getReadbackBufferFence(getPrimaryDisplayId()); |
| |
| EXPECT_FALSE(status.isOk()); |
| EXPECT_NO_FATAL_FAILURE(assertServiceSpecificError(status, IComposerClient::EX_UNSUPPORTED)); |
| EXPECT_EQ(-1, releaseFence.get()); |
| } |
| |
| TEST_P(GraphicsCompositionTest, ClientComposition) { |
| EXPECT_TRUE( |
| mComposerClient->setClientTargetSlotCount(getPrimaryDisplayId(), kClientTargetSlotCount) |
| .isOk()); |
| |
| for (ColorMode mode : mTestColorModes) { |
| EXPECT_TRUE(mComposerClient |
| ->setColorMode(getPrimaryDisplayId(), mode, RenderIntent::COLORIMETRIC) |
| .isOk()); |
| |
| bool isSupported; |
| ASSERT_NO_FATAL_FAILURE(isSupported = getHasReadbackBuffer()); |
| if (!isSupported) { |
| GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace"; |
| return; |
| } |
| |
| std::vector<Color> expectedColors( |
| static_cast<size_t>(getDisplayWidth() * getDisplayHeight())); |
| ReadbackHelper::fillColorsArea(expectedColors, getDisplayWidth(), |
| {0, 0, getDisplayWidth(), getDisplayHeight() / 4}, RED); |
| ReadbackHelper::fillColorsArea( |
| expectedColors, getDisplayWidth(), |
| {0, getDisplayHeight() / 4, getDisplayWidth(), getDisplayHeight() / 2}, GREEN); |
| ReadbackHelper::fillColorsArea( |
| expectedColors, getDisplayWidth(), |
| {0, getDisplayHeight() / 2, getDisplayWidth(), getDisplayHeight()}, BLUE); |
| |
| auto layer = std::make_shared<TestBufferLayer>( |
| mComposerClient, *mTestRenderEngine, getPrimaryDisplayId(), getDisplayWidth(), |
| getDisplayHeight(), PixelFormat::RGBA_FP16, *mWriter); |
| layer->setDisplayFrame({0, 0, getDisplayWidth(), getDisplayHeight()}); |
| layer->setZOrder(10); |
| layer->setDataspace(ReadbackHelper::getDataspaceForColorMode(mode)); |
| |
| std::vector<std::shared_ptr<TestLayer>> layers = {layer}; |
| |
| ReadbackBuffer readbackBuffer(getPrimaryDisplayId(), mComposerClient, getDisplayWidth(), |
| getDisplayHeight(), mPixelFormat, mDataspace); |
| ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer()); |
| writeLayers(layers); |
| ASSERT_TRUE(mReader.takeErrors().empty()); |
| mWriter->validateDisplay(getPrimaryDisplayId(), ComposerClientWriter::kNoTimestamp, |
| VtsComposerClient::kNoFrameIntervalNs); |
| execute(); |
| |
| auto changedCompositionTypes = mReader.takeChangedCompositionTypes(getPrimaryDisplayId()); |
| if (!changedCompositionTypes.empty()) { |
| ASSERT_EQ(1, changedCompositionTypes.size()); |
| ASSERT_EQ(Composition::CLIENT, changedCompositionTypes[0].composition); |
| |
| PixelFormat clientFormat = PixelFormat::RGBA_8888; |
| auto clientUsage = static_cast<uint32_t>( |
| static_cast<uint32_t>(common::BufferUsage::CPU_READ_OFTEN) | |
| static_cast<uint32_t>(common::BufferUsage::CPU_WRITE_OFTEN) | |
| static_cast<uint32_t>(common::BufferUsage::COMPOSER_CLIENT_TARGET)); |
| Dataspace clientDataspace = ReadbackHelper::getDataspaceForColorMode(mode); |
| common::Rect damage{0, 0, getDisplayWidth(), getDisplayHeight()}; |
| |
| // create client target buffer |
| const auto& [graphicBufferStatus, graphicBuffer] = allocateBuffer(clientUsage); |
| ASSERT_TRUE(graphicBufferStatus); |
| const auto& buffer = graphicBuffer->handle; |
| void* clientBufData; |
| const auto stride = static_cast<uint32_t>(graphicBuffer->stride); |
| graphicBuffer->lock(clientUsage, layer->getAccessRegion(), &clientBufData); |
| |
| ASSERT_NO_FATAL_FAILURE( |
| ReadbackHelper::fillBuffer(layer->getWidth(), layer->getHeight(), stride, |
| clientBufData, clientFormat, expectedColors)); |
| int32_t clientFence; |
| const auto unlockStatus = graphicBuffer->unlockAsync(&clientFence); |
| ASSERT_EQ(::android::OK, unlockStatus); |
| mWriter->setClientTarget(getPrimaryDisplayId(), /*slot*/ 0, buffer, clientFence, |
| clientDataspace, std::vector<common::Rect>(1, damage), 1.f); |
| layer->setToClientComposition(*mWriter); |
| mWriter->validateDisplay(getPrimaryDisplayId(), ComposerClientWriter::kNoTimestamp, |
| VtsComposerClient::kNoFrameIntervalNs); |
| execute(); |
| changedCompositionTypes = mReader.takeChangedCompositionTypes(getPrimaryDisplayId()); |
| ASSERT_TRUE(changedCompositionTypes.empty()); |
| } |
| ASSERT_TRUE(mReader.takeErrors().empty()); |
| |
| mWriter->presentDisplay(getPrimaryDisplayId()); |
| execute(); |
| |
| ASSERT_TRUE(mReader.takeErrors().empty()); |
| |
| ASSERT_NO_FATAL_FAILURE(readbackBuffer.checkReadbackBuffer(expectedColors)); |
| } |
| } |
| |
| TEST_P(GraphicsCompositionTest, MixedColorSpaces) { |
| ASSERT_TRUE( |
| mComposerClient->setClientTargetSlotCount(getPrimaryDisplayId(), kClientTargetSlotCount) |
| .isOk()); |
| const auto& [status, properties] = mComposerClient->getOverlaySupport(); |
| if (!status.isOk() && status.getExceptionCode() == EX_SERVICE_SPECIFIC && |
| status.getServiceSpecificError() == IComposerClient::EX_UNSUPPORTED) { |
| GTEST_SUCCEED() << "getOverlaySupport is not supported"; |
| return; |
| } |
| |
| if (properties.supportMixedColorSpaces == false) { |
| GTEST_SUCCEED() << "supportMixedColorSpaces is not supported"; |
| return; |
| } |
| |
| for (ColorMode mode : mTestColorModes) { |
| EXPECT_TRUE(mComposerClient |
| ->setColorMode(getPrimaryDisplayId(), mode, RenderIntent::COLORIMETRIC) |
| .isOk()); |
| |
| bool isSupported; |
| ASSERT_NO_FATAL_FAILURE(isSupported = getHasReadbackBuffer()); |
| if (!isSupported) { |
| GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace"; |
| return; |
| } |
| |
| // sRGB layer |
| auto srgbLayer = std::make_shared<TestBufferLayer>( |
| mComposerClient, *mTestRenderEngine, getPrimaryDisplayId(), getDisplayWidth(), |
| getDisplayHeight() / 2, PixelFormat::RGBA_8888, *mWriter); |
| std::vector<Color> sRgbDeviceColors(srgbLayer->getWidth() * srgbLayer->getHeight()); |
| ReadbackHelper::fillColorsArea(sRgbDeviceColors, getDisplayWidth(), |
| {0, 0, static_cast<int32_t>(srgbLayer->getWidth()), |
| static_cast<int32_t>(srgbLayer->getHeight())}, |
| GREEN); |
| srgbLayer->setDisplayFrame({0, 0, static_cast<int32_t>(srgbLayer->getWidth()), |
| static_cast<int32_t>(srgbLayer->getHeight())}); |
| srgbLayer->setZOrder(10); |
| srgbLayer->setDataspace(Dataspace::SRGB); |
| ASSERT_NO_FATAL_FAILURE(srgbLayer->setBuffer(sRgbDeviceColors)); |
| |
| // display P3 layer |
| auto displayP3Layer = std::make_shared<TestBufferLayer>( |
| mComposerClient, *mTestRenderEngine, getPrimaryDisplayId(), getDisplayWidth(), |
| getDisplayHeight() / 2, PixelFormat::RGBA_8888, *mWriter); |
| std::vector<Color> displayP3DeviceColors( |
| static_cast<size_t>(displayP3Layer->getWidth() * displayP3Layer->getHeight())); |
| ReadbackHelper::fillColorsArea(displayP3DeviceColors, getDisplayWidth(), |
| {0, 0, static_cast<int32_t>(displayP3Layer->getWidth()), |
| static_cast<int32_t>(displayP3Layer->getHeight())}, |
| RED); |
| displayP3Layer->setDisplayFrame( |
| {0, getDisplayHeight() / 2, getDisplayWidth(), getDisplayHeight()}); |
| displayP3Layer->setZOrder(10); |
| displayP3Layer->setDataspace(Dataspace::DISPLAY_P3); |
| ASSERT_NO_FATAL_FAILURE(displayP3Layer->setBuffer(displayP3DeviceColors)); |
| |
| writeLayers({srgbLayer, displayP3Layer}); |
| |
| mWriter->validateDisplay(getPrimaryDisplayId(), ComposerClientWriter::kNoTimestamp, |
| VtsComposerClient::kNoFrameIntervalNs); |
| execute(); |
| |
| auto changedCompositionTypes = mReader.takeChangedCompositionTypes(getPrimaryDisplayId()); |
| ASSERT_TRUE(changedCompositionTypes.empty()); |
| |
| mWriter->presentDisplay(getPrimaryDisplayId()); |
| execute(); |
| |
| changedCompositionTypes = mReader.takeChangedCompositionTypes(getPrimaryDisplayId()); |
| ASSERT_TRUE(changedCompositionTypes.empty()); |
| ASSERT_TRUE(mReader.takeErrors().empty()); |
| } |
| } |
| |
| TEST_P(GraphicsCompositionTest, DeviceAndClientComposition) { |
| ASSERT_TRUE( |
| mComposerClient->setClientTargetSlotCount(getPrimaryDisplayId(), kClientTargetSlotCount) |
| .isOk()); |
| |
| for (ColorMode mode : mTestColorModes) { |
| EXPECT_TRUE(mComposerClient |
| ->setColorMode(getPrimaryDisplayId(), mode, RenderIntent::COLORIMETRIC) |
| .isOk()); |
| |
| bool isSupported; |
| ASSERT_NO_FATAL_FAILURE(isSupported = getHasReadbackBuffer()); |
| if (!isSupported) { |
| GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace"; |
| return; |
| } |
| |
| std::vector<Color> expectedColors( |
| static_cast<size_t>(getDisplayWidth() * getDisplayHeight())); |
| ReadbackHelper::fillColorsArea(expectedColors, getDisplayWidth(), |
| {0, 0, getDisplayWidth(), getDisplayHeight() / 2}, GREEN); |
| ReadbackHelper::fillColorsArea( |
| expectedColors, getDisplayWidth(), |
| {0, getDisplayHeight() / 2, getDisplayWidth(), getDisplayHeight()}, RED); |
| |
| ReadbackBuffer readbackBuffer(getPrimaryDisplayId(), mComposerClient, getDisplayWidth(), |
| getDisplayHeight(), mPixelFormat, mDataspace); |
| ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer()); |
| |
| auto deviceLayer = std::make_shared<TestBufferLayer>( |
| mComposerClient, *mTestRenderEngine, getPrimaryDisplayId(), getDisplayWidth(), |
| getDisplayHeight() / 2, PixelFormat::RGBA_8888, *mWriter); |
| std::vector<Color> deviceColors(deviceLayer->getWidth() * deviceLayer->getHeight()); |
| ReadbackHelper::fillColorsArea(deviceColors, static_cast<int32_t>(deviceLayer->getWidth()), |
| {0, 0, static_cast<int32_t>(deviceLayer->getWidth()), |
| static_cast<int32_t>(deviceLayer->getHeight())}, |
| GREEN); |
| deviceLayer->setDisplayFrame({0, 0, static_cast<int32_t>(deviceLayer->getWidth()), |
| static_cast<int32_t>(deviceLayer->getHeight())}); |
| deviceLayer->setZOrder(10); |
| deviceLayer->setDataspace(ReadbackHelper::getDataspaceForColorMode(mode)); |
| ASSERT_NO_FATAL_FAILURE(deviceLayer->setBuffer(deviceColors)); |
| deviceLayer->write(*mWriter); |
| |
| PixelFormat clientFormat = PixelFormat::RGBA_8888; |
| auto clientUsage = static_cast<uint32_t>( |
| static_cast<uint64_t>(common::BufferUsage::CPU_READ_OFTEN) | |
| static_cast<uint32_t>(common::BufferUsage::CPU_WRITE_OFTEN) | |
| static_cast<uint32_t>(common::BufferUsage::COMPOSER_CLIENT_TARGET)); |
| Dataspace clientDataspace = ReadbackHelper::getDataspaceForColorMode(mode); |
| int32_t clientWidth = getDisplayWidth(); |
| int32_t clientHeight = getDisplayHeight() / 2; |
| |
| auto clientLayer = std::make_shared<TestBufferLayer>( |
| mComposerClient, *mTestRenderEngine, getPrimaryDisplayId(), clientWidth, |
| clientHeight, PixelFormat::RGBA_FP16, *mWriter, Composition::DEVICE); |
| common::Rect clientFrame = {0, getDisplayHeight() / 2, getDisplayWidth(), |
| getDisplayHeight()}; |
| clientLayer->setDisplayFrame(clientFrame); |
| clientLayer->setZOrder(0); |
| clientLayer->write(*mWriter); |
| mWriter->validateDisplay(getPrimaryDisplayId(), ComposerClientWriter::kNoTimestamp, |
| VtsComposerClient::kNoFrameIntervalNs); |
| execute(); |
| |
| auto changedCompositionTypes = mReader.takeChangedCompositionTypes(getPrimaryDisplayId()); |
| if (changedCompositionTypes.size() != 1) { |
| continue; |
| } |
| // create client target buffer |
| ASSERT_EQ(Composition::CLIENT, changedCompositionTypes[0].composition); |
| const auto& [graphicBufferStatus, graphicBuffer] = allocateBuffer(clientUsage); |
| ASSERT_TRUE(graphicBufferStatus); |
| const auto& buffer = graphicBuffer->handle; |
| |
| void* clientBufData; |
| graphicBuffer->lock(clientUsage, {0, 0, getDisplayWidth(), getDisplayHeight()}, |
| &clientBufData); |
| |
| std::vector<Color> clientColors( |
| static_cast<size_t>(getDisplayWidth() * getDisplayHeight())); |
| ReadbackHelper::fillColorsArea(clientColors, getDisplayWidth(), clientFrame, RED); |
| ASSERT_NO_FATAL_FAILURE(ReadbackHelper::fillBuffer( |
| static_cast<uint32_t>(getDisplayWidth()), static_cast<uint32_t>(getDisplayHeight()), |
| graphicBuffer->getStride(), clientBufData, clientFormat, clientColors)); |
| int32_t clientFence; |
| const auto unlockStatus = graphicBuffer->unlockAsync(&clientFence); |
| ASSERT_EQ(::android::OK, unlockStatus); |
| mWriter->setClientTarget(getPrimaryDisplayId(), /*slot*/ 0, buffer, clientFence, |
| clientDataspace, std::vector<common::Rect>(1, clientFrame), 1.f); |
| clientLayer->setToClientComposition(*mWriter); |
| mWriter->validateDisplay(getPrimaryDisplayId(), ComposerClientWriter::kNoTimestamp, |
| VtsComposerClient::kNoFrameIntervalNs); |
| execute(); |
| changedCompositionTypes = mReader.takeChangedCompositionTypes(getPrimaryDisplayId()); |
| ASSERT_TRUE(changedCompositionTypes.empty()); |
| ASSERT_TRUE(mReader.takeErrors().empty()); |
| |
| mWriter->presentDisplay(getPrimaryDisplayId()); |
| execute(); |
| ASSERT_TRUE(mReader.takeErrors().empty()); |
| ASSERT_NO_FATAL_FAILURE(readbackBuffer.checkReadbackBuffer(expectedColors)); |
| } |
| } |
| |
| TEST_P(GraphicsCompositionTest, SetLayerDamage) { |
| for (ColorMode mode : mTestColorModes) { |
| EXPECT_TRUE(mComposerClient |
| ->setColorMode(getPrimaryDisplayId(), mode, RenderIntent::COLORIMETRIC) |
| .isOk()); |
| |
| bool isSupported; |
| ASSERT_NO_FATAL_FAILURE(isSupported = getHasReadbackBuffer()); |
| if (!isSupported) { |
| GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace"; |
| return; |
| } |
| |
| common::Rect redRect = {0, 0, getDisplayWidth() / 4, getDisplayHeight() / 4}; |
| |
| std::vector<Color> expectedColors( |
| static_cast<size_t>(getDisplayWidth() * getDisplayHeight())); |
| ReadbackHelper::fillColorsArea(expectedColors, getDisplayWidth(), redRect, RED); |
| |
| auto layer = std::make_shared<TestBufferLayer>( |
| mComposerClient, *mTestRenderEngine, getPrimaryDisplayId(), getDisplayWidth(), |
| getDisplayHeight(), PixelFormat::RGBA_8888, *mWriter); |
| layer->setDisplayFrame({0, 0, getDisplayWidth(), getDisplayHeight()}); |
| layer->setZOrder(10); |
| layer->setDataspace(ReadbackHelper::getDataspaceForColorMode(mode)); |
| ASSERT_NO_FATAL_FAILURE(layer->setBuffer(expectedColors)); |
| |
| std::vector<std::shared_ptr<TestLayer>> layers = {layer}; |
| |
| ReadbackBuffer readbackBuffer(getPrimaryDisplayId(), mComposerClient, getDisplayWidth(), |
| getDisplayHeight(), mPixelFormat, mDataspace); |
| ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer()); |
| |
| writeLayers(layers); |
| ASSERT_TRUE(mReader.takeErrors().empty()); |
| mWriter->validateDisplay(getPrimaryDisplayId(), ComposerClientWriter::kNoTimestamp, |
| VtsComposerClient::kNoFrameIntervalNs); |
| execute(); |
| if (!mReader.takeChangedCompositionTypes(getPrimaryDisplayId()).empty()) { |
| GTEST_SUCCEED(); |
| return; |
| } |
| ASSERT_TRUE(mReader.takeErrors().empty()); |
| mWriter->presentDisplay(getPrimaryDisplayId()); |
| execute(); |
| ASSERT_TRUE(mReader.takeErrors().empty()); |
| |
| ASSERT_NO_FATAL_FAILURE(readbackBuffer.checkReadbackBuffer(expectedColors)); |
| |
| // update surface damage and recheck |
| redRect = {getDisplayWidth() / 4, getDisplayHeight() / 4, getDisplayWidth() / 2, |
| getDisplayHeight() / 2}; |
| ReadbackHelper::clearColors(expectedColors, getDisplayWidth(), getDisplayHeight(), |
| getDisplayWidth()); |
| ReadbackHelper::fillColorsArea(expectedColors, getDisplayWidth(), redRect, RED); |
| |
| ASSERT_NO_FATAL_FAILURE(layer->fillBuffer(expectedColors)); |
| layer->setSurfaceDamage( |
| std::vector<common::Rect>(1, {0, 0, getDisplayWidth() / 2, getDisplayWidth() / 2})); |
| |
| ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer()); |
| |
| writeLayers(layers); |
| ASSERT_TRUE(mReader.takeErrors().empty()); |
| mWriter->validateDisplay(getPrimaryDisplayId(), ComposerClientWriter::kNoTimestamp, |
| VtsComposerClient::kNoFrameIntervalNs); |
| execute(); |
| ASSERT_TRUE(mReader.takeErrors().empty()); |
| ASSERT_TRUE(mReader.takeChangedCompositionTypes(getPrimaryDisplayId()).empty()); |
| mWriter->presentDisplay(getPrimaryDisplayId()); |
| execute(); |
| ASSERT_TRUE(mReader.takeErrors().empty()); |
| |
| ASSERT_NO_FATAL_FAILURE(readbackBuffer.checkReadbackBuffer(expectedColors)); |
| } |
| } |
| |
| TEST_P(GraphicsCompositionTest, SetLayerPlaneAlpha) { |
| for (ColorMode mode : mTestColorModes) { |
| EXPECT_TRUE(mComposerClient |
| ->setColorMode(getPrimaryDisplayId(), mode, RenderIntent::COLORIMETRIC) |
| .isOk()); |
| |
| bool isSupported; |
| ASSERT_NO_FATAL_FAILURE(isSupported = getHasReadbackBuffer()); |
| if (!isSupported) { |
| GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace"; |
| return; |
| } |
| |
| auto layer = |
| std::make_shared<TestColorLayer>(mComposerClient, getPrimaryDisplayId(), *mWriter); |
| layer->setColor(RED); |
| layer->setDisplayFrame({0, 0, getDisplayWidth(), getDisplayHeight()}); |
| layer->setZOrder(10); |
| layer->setAlpha(0); |
| layer->setBlendMode(BlendMode::PREMULTIPLIED); |
| |
| std::vector<std::shared_ptr<TestLayer>> layers = {layer}; |
| |
| ReadbackBuffer readbackBuffer(getPrimaryDisplayId(), mComposerClient, getDisplayWidth(), |
| getDisplayHeight(), mPixelFormat, mDataspace); |
| |
| ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer()); |
| |
| writeLayers(layers); |
| ASSERT_TRUE(mReader.takeErrors().empty()); |
| mWriter->validateDisplay(getPrimaryDisplayId(), ComposerClientWriter::kNoTimestamp, |
| VtsComposerClient::kNoFrameIntervalNs); |
| execute(); |
| if (!mReader.takeChangedCompositionTypes(getPrimaryDisplayId()).empty()) { |
| GTEST_SUCCEED(); |
| return; |
| } |
| ASSERT_TRUE(mReader.takeErrors().empty()); |
| |
| mWriter->presentDisplay(getPrimaryDisplayId()); |
| execute(); |
| ASSERT_TRUE(mReader.takeErrors().empty()); |
| |
| std::vector<Color> expectedColors( |
| static_cast<size_t>(getDisplayWidth() * getDisplayHeight())); |
| |
| ASSERT_NO_FATAL_FAILURE(readbackBuffer.checkReadbackBuffer(expectedColors)); |
| mTestRenderEngine->setRenderLayers(layers); |
| ASSERT_NO_FATAL_FAILURE(mTestRenderEngine->drawLayers()); |
| ASSERT_NO_FATAL_FAILURE(mTestRenderEngine->checkColorBuffer(expectedColors)); |
| } |
| } |
| |
| TEST_P(GraphicsCompositionTest, SetLayerSourceCrop) { |
| for (ColorMode mode : mTestColorModes) { |
| EXPECT_TRUE(mComposerClient |
| ->setColorMode(getPrimaryDisplayId(), mode, RenderIntent::COLORIMETRIC) |
| .isOk()); |
| |
| bool isSupported; |
| ASSERT_NO_FATAL_FAILURE(isSupported = getHasReadbackBuffer()); |
| if (!isSupported) { |
| GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace"; |
| return; |
| } |
| |
| std::vector<Color> expectedColors( |
| static_cast<size_t>(getDisplayWidth() * getDisplayHeight())); |
| ReadbackHelper::fillColorsArea(expectedColors, getDisplayWidth(), |
| {0, 0, getDisplayWidth(), getDisplayHeight() / 4}, RED); |
| ReadbackHelper::fillColorsArea( |
| expectedColors, getDisplayWidth(), |
| {0, getDisplayHeight() / 2, getDisplayWidth(), getDisplayHeight()}, BLUE); |
| |
| auto layer = std::make_shared<TestBufferLayer>( |
| mComposerClient, *mTestRenderEngine, getPrimaryDisplayId(), getDisplayWidth(), |
| getDisplayHeight(), PixelFormat::RGBA_8888, *mWriter); |
| layer->setDisplayFrame({0, 0, getDisplayWidth(), getDisplayHeight()}); |
| layer->setZOrder(10); |
| layer->setDataspace(ReadbackHelper::getDataspaceForColorMode(mode)); |
| layer->setSourceCrop({0, static_cast<float>(getDisplayHeight() / 2), |
| static_cast<float>(getDisplayWidth()), |
| static_cast<float>(getDisplayHeight())}); |
| ASSERT_NO_FATAL_FAILURE(layer->setBuffer(expectedColors)); |
| |
| std::vector<std::shared_ptr<TestLayer>> layers = {layer}; |
| |
| // update expected colors to match crop |
| ReadbackHelper::fillColorsArea(expectedColors, getDisplayWidth(), |
| {0, 0, getDisplayWidth(), getDisplayHeight()}, BLUE); |
| ReadbackBuffer readbackBuffer(getPrimaryDisplayId(), mComposerClient, getDisplayWidth(), |
| getDisplayHeight(), mPixelFormat, mDataspace); |
| ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer()); |
| writeLayers(layers); |
| ASSERT_TRUE(mReader.takeErrors().empty()); |
| mWriter->validateDisplay(getPrimaryDisplayId(), ComposerClientWriter::kNoTimestamp, |
| VtsComposerClient::kNoFrameIntervalNs); |
| execute(); |
| if (!mReader.takeChangedCompositionTypes(getPrimaryDisplayId()).empty()) { |
| GTEST_SUCCEED(); |
| return; |
| } |
| ASSERT_TRUE(mReader.takeErrors().empty()); |
| mWriter->presentDisplay(getPrimaryDisplayId()); |
| execute(); |
| ASSERT_TRUE(mReader.takeErrors().empty()); |
| ASSERT_NO_FATAL_FAILURE(readbackBuffer.checkReadbackBuffer(expectedColors)); |
| mTestRenderEngine->setRenderLayers(layers); |
| ASSERT_NO_FATAL_FAILURE(mTestRenderEngine->drawLayers()); |
| ASSERT_NO_FATAL_FAILURE(mTestRenderEngine->checkColorBuffer(expectedColors)); |
| } |
| } |
| |
| TEST_P(GraphicsCompositionTest, SetLayerZOrder) { |
| for (ColorMode mode : mTestColorModes) { |
| EXPECT_TRUE(mComposerClient |
| ->setColorMode(getPrimaryDisplayId(), mode, RenderIntent::COLORIMETRIC) |
| .isOk()); |
| |
| bool isSupported; |
| ASSERT_NO_FATAL_FAILURE(isSupported = getHasReadbackBuffer()); |
| if (!isSupported) { |
| GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace"; |
| return; |
| } |
| |
| common::Rect redRect = {0, 0, getDisplayWidth(), getDisplayHeight() / 2}; |
| common::Rect blueRect = {0, getDisplayHeight() / 4, getDisplayWidth(), getDisplayHeight()}; |
| auto redLayer = |
| std::make_shared<TestColorLayer>(mComposerClient, getPrimaryDisplayId(), *mWriter); |
| redLayer->setColor(RED); |
| redLayer->setDisplayFrame(redRect); |
| |
| auto blueLayer = |
| std::make_shared<TestColorLayer>(mComposerClient, getPrimaryDisplayId(), *mWriter); |
| blueLayer->setColor(BLUE); |
| blueLayer->setDisplayFrame(blueRect); |
| blueLayer->setZOrder(5); |
| |
| std::vector<std::shared_ptr<TestLayer>> layers = {redLayer, blueLayer}; |
| std::vector<Color> expectedColors( |
| static_cast<size_t>(getDisplayWidth() * getDisplayHeight())); |
| |
| // red in front of blue |
| redLayer->setZOrder(10); |
| |
| // fill blue first so that red will overwrite on overlap |
| ReadbackHelper::fillColorsArea(expectedColors, getDisplayWidth(), blueRect, BLUE); |
| ReadbackHelper::fillColorsArea(expectedColors, getDisplayWidth(), redRect, RED); |
| |
| ReadbackBuffer readbackBuffer(getPrimaryDisplayId(), mComposerClient, getDisplayWidth(), |
| getDisplayHeight(), mPixelFormat, mDataspace); |
| ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer()); |
| |
| writeLayers(layers); |
| ASSERT_TRUE(mReader.takeErrors().empty()); |
| mWriter->validateDisplay(getPrimaryDisplayId(), ComposerClientWriter::kNoTimestamp, |
| VtsComposerClient::kNoFrameIntervalNs); |
| execute(); |
| if (!mReader.takeChangedCompositionTypes(getPrimaryDisplayId()).empty()) { |
| GTEST_SUCCEED(); |
| return; |
| } |
| mWriter->presentDisplay(getPrimaryDisplayId()); |
| execute(); |
| ASSERT_TRUE(mReader.takeErrors().empty()); |
| |
| ASSERT_NO_FATAL_FAILURE(readbackBuffer.checkReadbackBuffer(expectedColors)); |
| |
| redLayer->setZOrder(1); |
| ReadbackHelper::clearColors(expectedColors, getDisplayWidth(), getDisplayHeight(), |
| getDisplayWidth()); |
| ReadbackHelper::fillColorsArea(expectedColors, getDisplayWidth(), redRect, RED); |
| ReadbackHelper::fillColorsArea(expectedColors, getDisplayWidth(), blueRect, BLUE); |
| |
| ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer()); |
| |
| writeLayers(layers); |
| ASSERT_TRUE(mReader.takeErrors().empty()); |
| mWriter->validateDisplay(getPrimaryDisplayId(), ComposerClientWriter::kNoTimestamp, |
| VtsComposerClient::kNoFrameIntervalNs); |
| execute(); |
| ASSERT_TRUE(mReader.takeChangedCompositionTypes(getPrimaryDisplayId()).empty()); |
| ASSERT_TRUE(mReader.takeErrors().empty()); |
| mWriter->presentDisplay(getPrimaryDisplayId()); |
| execute(); |
| ASSERT_TRUE(mReader.takeErrors().empty()); |
| |
| ASSERT_NO_FATAL_FAILURE(readbackBuffer.checkReadbackBuffer(expectedColors)); |
| mTestRenderEngine->setRenderLayers(layers); |
| ASSERT_NO_FATAL_FAILURE(mTestRenderEngine->drawLayers()); |
| ASSERT_NO_FATAL_FAILURE(mTestRenderEngine->checkColorBuffer(expectedColors)); |
| } |
| } |
| |
| TEST_P(GraphicsCompositionTest, SetLayerBrightnessDims) { |
| for (ColorMode mode : mTestColorModes) { |
| EXPECT_TRUE(mComposerClient |
| ->setColorMode(getPrimaryDisplayId(), mode, RenderIntent::COLORIMETRIC) |
| .isOk()); |
| |
| bool isSupported; |
| ASSERT_NO_FATAL_FAILURE(isSupported = getHasReadbackBuffer()); |
| if (!isSupported) { |
| GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace for " |
| "color mode: " |
| << toString(mode); |
| continue; |
| } |
| const common::Rect redRect = {0, 0, getDisplayWidth(), getDisplayHeight() / 2}; |
| const common::Rect dimmerRedRect = {0, getDisplayHeight() / 2, getDisplayWidth(), |
| getDisplayHeight()}; |
| |
| static constexpr float kMaxBrightnessNits = 300.f; |
| |
| const auto redLayer = |
| std::make_shared<TestColorLayer>(mComposerClient, getPrimaryDisplayId(), *mWriter); |
| redLayer->setColor(RED); |
| redLayer->setDisplayFrame(redRect); |
| redLayer->setWhitePointNits(kMaxBrightnessNits); |
| redLayer->setBrightness(1.f); |
| |
| const auto dimmerRedLayer = |
| std::make_shared<TestColorLayer>(mComposerClient, getPrimaryDisplayId(), *mWriter); |
| dimmerRedLayer->setColor(RED); |
| dimmerRedLayer->setDisplayFrame(dimmerRedRect); |
| // Intentionally use a small dimming ratio as some implementations may be more likely to |
| // kick into GPU composition to apply dithering when the dimming ratio is high. |
| static constexpr float kDimmingRatio = 0.9f; |
| dimmerRedLayer->setWhitePointNits(kMaxBrightnessNits * kDimmingRatio); |
| dimmerRedLayer->setBrightness(kDimmingRatio); |
| |
| const std::vector<std::shared_ptr<TestLayer>> layers = {redLayer, dimmerRedLayer}; |
| std::vector<Color> expectedColors( |
| static_cast<size_t>(getDisplayWidth() * getDisplayHeight())); |
| |
| ReadbackHelper::fillColorsArea(expectedColors, getDisplayWidth(), redRect, RED); |
| ReadbackHelper::fillColorsArea(expectedColors, getDisplayWidth(), dimmerRedRect, DIM_RED); |
| |
| ReadbackBuffer readbackBuffer(getPrimaryDisplayId(), mComposerClient, getDisplayWidth(), |
| getDisplayHeight(), mPixelFormat, mDataspace); |
| ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer()); |
| |
| writeLayers(layers); |
| ASSERT_TRUE(mReader.takeErrors().empty()); |
| mWriter->validateDisplay(getPrimaryDisplayId(), ComposerClientWriter::kNoTimestamp, |
| VtsComposerClient::kNoFrameIntervalNs); |
| execute(); |
| if (!mReader.takeChangedCompositionTypes(getPrimaryDisplayId()).empty()) { |
| GTEST_SUCCEED() |
| << "Readback verification not supported for GPU composition for color mode: " |
| << toString(mode); |
| continue; |
| } |
| mWriter->presentDisplay(getPrimaryDisplayId()); |
| execute(); |
| ASSERT_TRUE(mReader.takeErrors().empty()); |
| |
| ASSERT_NO_FATAL_FAILURE(readbackBuffer.checkReadbackBuffer(expectedColors)); |
| mTestRenderEngine->setRenderLayers(layers); |
| ASSERT_NO_FATAL_FAILURE(mTestRenderEngine->drawLayers()); |
| ASSERT_NO_FATAL_FAILURE(mTestRenderEngine->checkColorBuffer(expectedColors)); |
| } |
| } |
| |
| class GraphicsBlendModeCompositionTest |
| : public GraphicsCompositionTestBase, |
| public testing::WithParamInterface<std::tuple<std::string, std::string>> { |
| public: |
| void SetUp() override { |
| SetUpBase(std::get<0>(GetParam())); |
| // TODO(b/219590743) we should remove the below SRGB color mode |
| // once we have the BlendMode test fix for all the versions of the ColorMode |
| mTestColorModes.erase( |
| std::remove_if(mTestColorModes.begin(), mTestColorModes.end(), |
| [](ColorMode mode) { return mode != ColorMode::SRGB; }), |
| mTestColorModes.end()); |
| mBackgroundColor = BLACK; |
| mTopLayerColor = RED; |
| } |
| |
| void setBackgroundColor(Color color) { mBackgroundColor = color; } |
| |
| void setTopLayerColor(Color color) { mTopLayerColor = color; } |
| |
| void setUpLayers(BlendMode blendMode) { |
| mLayers.clear(); |
| std::vector<Color> topLayerPixelColors( |
| static_cast<size_t>(getDisplayWidth() * getDisplayHeight())); |
| ReadbackHelper::fillColorsArea(topLayerPixelColors, getDisplayWidth(), |
| {0, 0, getDisplayWidth(), getDisplayHeight()}, |
| mTopLayerColor); |
| |
| auto backgroundLayer = |
| std::make_shared<TestColorLayer>(mComposerClient, getPrimaryDisplayId(), *mWriter); |
| backgroundLayer->setDisplayFrame({0, 0, getDisplayWidth(), getDisplayHeight()}); |
| backgroundLayer->setZOrder(0); |
| backgroundLayer->setColor(mBackgroundColor); |
| |
| auto layer = std::make_shared<TestBufferLayer>( |
| mComposerClient, *mTestRenderEngine, getPrimaryDisplayId(), getDisplayWidth(), |
| getDisplayHeight(), PixelFormat::RGBA_8888, *mWriter); |
| layer->setDisplayFrame({0, 0, getDisplayWidth(), getDisplayHeight()}); |
| layer->setZOrder(10); |
| layer->setDataspace(Dataspace::UNKNOWN); |
| ASSERT_NO_FATAL_FAILURE(layer->setBuffer(topLayerPixelColors)); |
| |
| layer->setBlendMode(blendMode); |
| layer->setAlpha(std::stof(std::get<1>(GetParam()))); |
| |
| mLayers.push_back(backgroundLayer); |
| mLayers.push_back(layer); |
| } |
| |
| void setExpectedColors(std::vector<Color>& expectedColors) { |
| ASSERT_EQ(2, mLayers.size()); |
| ReadbackHelper::clearColors(expectedColors, getDisplayWidth(), getDisplayHeight(), |
| getDisplayWidth()); |
| |
| auto layer = mLayers[1]; |
| BlendMode blendMode = layer->getBlendMode(); |
| float alpha = mTopLayerColor.a * layer->getAlpha(); |
| if (blendMode == BlendMode::NONE) { |
| for (auto& expectedColor : expectedColors) { |
| expectedColor.r = mTopLayerColor.r * layer->getAlpha(); |
| expectedColor.g = mTopLayerColor.g * layer->getAlpha(); |
| expectedColor.b = mTopLayerColor.b * layer->getAlpha(); |
| expectedColor.a = alpha; |
| } |
| } else if (blendMode == BlendMode::PREMULTIPLIED) { |
| for (auto& expectedColor : expectedColors) { |
| expectedColor.r = |
| mTopLayerColor.r * layer->getAlpha() + mBackgroundColor.r * (1.0f - alpha); |
| expectedColor.g = |
| mTopLayerColor.g * layer->getAlpha() + mBackgroundColor.g * (1.0f - alpha); |
| expectedColor.b = |
| mTopLayerColor.b * layer->getAlpha() + mBackgroundColor.b * (1.0f - alpha); |
| expectedColor.a = alpha + mBackgroundColor.a * (1.0f - alpha); |
| } |
| } else if (blendMode == BlendMode::COVERAGE) { |
| for (auto& expectedColor : expectedColors) { |
| expectedColor.r = mTopLayerColor.r * alpha + mBackgroundColor.r * (1.0f - alpha); |
| expectedColor.g = mTopLayerColor.g * alpha + mBackgroundColor.g * (1.0f - alpha); |
| expectedColor.b = mTopLayerColor.b * alpha + mBackgroundColor.b * (1.0f - alpha); |
| expectedColor.a = mTopLayerColor.a * alpha + mBackgroundColor.a * (1.0f - alpha); |
| } |
| } |
| } |
| |
| protected: |
| std::vector<std::shared_ptr<TestLayer>> mLayers; |
| Color mBackgroundColor; |
| Color mTopLayerColor; |
| }; |
| |
| TEST_P(GraphicsBlendModeCompositionTest, None) { |
| for (ColorMode mode : mTestColorModes) { |
| EXPECT_TRUE(mComposerClient |
| ->setColorMode(getPrimaryDisplayId(), mode, RenderIntent::COLORIMETRIC) |
| .isOk()); |
| |
| bool isSupported; |
| ASSERT_NO_FATAL_FAILURE(isSupported = getHasReadbackBuffer()); |
| if (!isSupported) { |
| GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace"; |
| return; |
| } |
| |
| std::vector<Color> expectedColors( |
| static_cast<size_t>(getDisplayWidth() * getDisplayHeight())); |
| |
| setBackgroundColor(BLACK); |
| setTopLayerColor(TRANSLUCENT_RED); |
| setUpLayers(BlendMode::NONE); |
| setExpectedColors(expectedColors); |
| |
| ReadbackBuffer readbackBuffer(getPrimaryDisplayId(), mComposerClient, getDisplayWidth(), |
| getDisplayHeight(), mPixelFormat, mDataspace); |
| ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer()); |
| writeLayers(mLayers); |
| ASSERT_TRUE(mReader.takeErrors().empty()); |
| mWriter->validateDisplay(getPrimaryDisplayId(), ComposerClientWriter::kNoTimestamp, |
| VtsComposerClient::kNoFrameIntervalNs); |
| execute(); |
| if (!mReader.takeChangedCompositionTypes(getPrimaryDisplayId()).empty()) { |
| GTEST_SUCCEED(); |
| return; |
| } |
| ASSERT_TRUE(mReader.takeErrors().empty()); |
| mWriter->presentDisplay(getPrimaryDisplayId()); |
| execute(); |
| ASSERT_TRUE(mReader.takeErrors().empty()); |
| |
| ASSERT_NO_FATAL_FAILURE(readbackBuffer.checkReadbackBuffer(expectedColors)); |
| mTestRenderEngine->setRenderLayers(mLayers); |
| ASSERT_NO_FATAL_FAILURE(mTestRenderEngine->drawLayers()); |
| ASSERT_NO_FATAL_FAILURE(mTestRenderEngine->checkColorBuffer(expectedColors)); |
| } |
| } |
| |
| TEST_P(GraphicsBlendModeCompositionTest, Coverage) { |
| for (ColorMode mode : mTestColorModes) { |
| EXPECT_TRUE(mComposerClient |
| ->setColorMode(getPrimaryDisplayId(), mode, RenderIntent::COLORIMETRIC) |
| .isOk()); |
| |
| bool isSupported; |
| ASSERT_NO_FATAL_FAILURE(isSupported = getHasReadbackBuffer()); |
| if (!isSupported) { |
| GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace"; |
| return; |
| } |
| |
| std::vector<Color> expectedColors( |
| static_cast<size_t>(getDisplayWidth() * getDisplayHeight())); |
| |
| setBackgroundColor(BLACK); |
| setTopLayerColor(TRANSLUCENT_RED); |
| |
| setUpLayers(BlendMode::COVERAGE); |
| setExpectedColors(expectedColors); |
| |
| ReadbackBuffer readbackBuffer(getPrimaryDisplayId(), mComposerClient, getDisplayWidth(), |
| getDisplayHeight(), mPixelFormat, mDataspace); |
| ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer()); |
| writeLayers(mLayers); |
| ASSERT_TRUE(mReader.takeErrors().empty()); |
| mWriter->validateDisplay(getPrimaryDisplayId(), ComposerClientWriter::kNoTimestamp, |
| VtsComposerClient::kNoFrameIntervalNs); |
| execute(); |
| if (!mReader.takeChangedCompositionTypes(getPrimaryDisplayId()).empty()) { |
| GTEST_SUCCEED(); |
| return; |
| } |
| ASSERT_TRUE(mReader.takeErrors().empty()); |
| mWriter->presentDisplay(getPrimaryDisplayId()); |
| execute(); |
| ASSERT_TRUE(mReader.takeErrors().empty()); |
| ASSERT_NO_FATAL_FAILURE(readbackBuffer.checkReadbackBuffer(expectedColors)); |
| } |
| } |
| |
| TEST_P(GraphicsBlendModeCompositionTest, Premultiplied) { |
| for (ColorMode mode : mTestColorModes) { |
| EXPECT_TRUE(mComposerClient |
| ->setColorMode(getPrimaryDisplayId(), mode, RenderIntent::COLORIMETRIC) |
| .isOk()); |
| |
| bool isSupported; |
| ASSERT_NO_FATAL_FAILURE(isSupported = getHasReadbackBuffer()); |
| if (!isSupported) { |
| GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace"; |
| return; |
| } |
| |
| std::vector<Color> expectedColors( |
| static_cast<size_t>(getDisplayWidth() * getDisplayHeight())); |
| |
| setBackgroundColor(BLACK); |
| setTopLayerColor(TRANSLUCENT_RED); |
| setUpLayers(BlendMode::PREMULTIPLIED); |
| setExpectedColors(expectedColors); |
| |
| ReadbackBuffer readbackBuffer(getPrimaryDisplayId(), mComposerClient, getDisplayWidth(), |
| getDisplayHeight(), mPixelFormat, mDataspace); |
| ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer()); |
| writeLayers(mLayers); |
| ASSERT_TRUE(mReader.takeErrors().empty()); |
| mWriter->validateDisplay(getPrimaryDisplayId(), ComposerClientWriter::kNoTimestamp, |
| VtsComposerClient::kNoFrameIntervalNs); |
| execute(); |
| if (!mReader.takeChangedCompositionTypes(getPrimaryDisplayId()).empty()) { |
| GTEST_SUCCEED(); |
| return; |
| } |
| ASSERT_TRUE(mReader.takeErrors().empty()); |
| mWriter->presentDisplay(getPrimaryDisplayId()); |
| execute(); |
| ASSERT_TRUE(mReader.takeErrors().empty()); |
| ASSERT_NO_FATAL_FAILURE(readbackBuffer.checkReadbackBuffer(expectedColors)); |
| mTestRenderEngine->setRenderLayers(mLayers); |
| ASSERT_NO_FATAL_FAILURE(mTestRenderEngine->drawLayers()); |
| ASSERT_NO_FATAL_FAILURE(mTestRenderEngine->checkColorBuffer(expectedColors)); |
| } |
| } |
| |
| class GraphicsTransformCompositionTest : public GraphicsCompositionTest { |
| protected: |
| void SetUp() override { |
| GraphicsCompositionTest::SetUp(); |
| |
| auto backgroundLayer = |
| std::make_shared<TestColorLayer>(mComposerClient, getPrimaryDisplayId(), *mWriter); |
| backgroundLayer->setColor({0.0f, 0.0f, 0.0f, 0.0f}); |
| backgroundLayer->setDisplayFrame({0, 0, getDisplayWidth(), getDisplayHeight()}); |
| backgroundLayer->setZOrder(0); |
| |
| mSideLength = |
| getDisplayWidth() < getDisplayHeight() ? getDisplayWidth() : getDisplayHeight(); |
| common::Rect redRect = {0, 0, mSideLength / 2, mSideLength / 2}; |
| common::Rect blueRect = {mSideLength / 2, mSideLength / 2, mSideLength, mSideLength}; |
| |
| mLayer = std::make_shared<TestBufferLayer>(mComposerClient, *mTestRenderEngine, |
| getPrimaryDisplayId(), mSideLength, mSideLength, |
| PixelFormat::RGBA_8888, *mWriter); |
| mLayer->setDisplayFrame({0, 0, mSideLength, mSideLength}); |
| mLayer->setZOrder(10); |
| |
| std::vector<Color> baseColors(static_cast<size_t>(mSideLength * mSideLength)); |
| ReadbackHelper::fillColorsArea(baseColors, mSideLength, redRect, RED); |
| ReadbackHelper::fillColorsArea(baseColors, mSideLength, blueRect, BLUE); |
| ASSERT_NO_FATAL_FAILURE(mLayer->setBuffer(baseColors)); |
| mLayers = {backgroundLayer, mLayer}; |
| } |
| |
| protected: |
| std::shared_ptr<TestBufferLayer> mLayer; |
| std::vector<std::shared_ptr<TestLayer>> mLayers; |
| int mSideLength; |
| }; |
| |
| TEST_P(GraphicsTransformCompositionTest, FLIP_H) { |
| for (ColorMode mode : mTestColorModes) { |
| auto status = mComposerClient->setColorMode(getPrimaryDisplayId(), mode, |
| RenderIntent::COLORIMETRIC); |
| if (!status.isOk() && status.getExceptionCode() == EX_SERVICE_SPECIFIC && |
| (status.getServiceSpecificError() == IComposerClient::EX_UNSUPPORTED || |
| status.getServiceSpecificError() == IComposerClient::EX_BAD_PARAMETER)) { |
| SUCCEED() << "ColorMode not supported, skip test"; |
| return; |
| } |
| |
| bool isSupported; |
| ASSERT_NO_FATAL_FAILURE(isSupported = getHasReadbackBuffer()); |
| if (!isSupported) { |
| GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace"; |
| return; |
| } |
| ReadbackBuffer readbackBuffer(getPrimaryDisplayId(), mComposerClient, getDisplayWidth(), |
| getDisplayHeight(), mPixelFormat, mDataspace); |
| ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer()); |
| mLayer->setTransform(Transform::FLIP_H); |
| mLayer->setDataspace(ReadbackHelper::getDataspaceForColorMode(mode)); |
| |
| std::vector<Color> expectedColors( |
| static_cast<size_t>(getDisplayWidth() * getDisplayHeight())); |
| ReadbackHelper::fillColorsArea(expectedColors, getDisplayWidth(), |
| {mSideLength / 2, 0, mSideLength, mSideLength / 2}, RED); |
| ReadbackHelper::fillColorsArea(expectedColors, getDisplayWidth(), |
| {0, mSideLength / 2, mSideLength / 2, mSideLength}, BLUE); |
| |
| writeLayers(mLayers); |
| ASSERT_TRUE(mReader.takeErrors().empty()); |
| mWriter->validateDisplay(getPrimaryDisplayId(), ComposerClientWriter::kNoTimestamp, |
| VtsComposerClient::kNoFrameIntervalNs); |
| execute(); |
| if (!mReader.takeChangedCompositionTypes(getPrimaryDisplayId()).empty()) { |
| GTEST_SUCCEED(); |
| return; |
| } |
| ASSERT_TRUE(mReader.takeErrors().empty()); |
| mWriter->presentDisplay(getPrimaryDisplayId()); |
| execute(); |
| ASSERT_TRUE(mReader.takeErrors().empty()); |
| |
| ASSERT_NO_FATAL_FAILURE(readbackBuffer.checkReadbackBuffer(expectedColors)); |
| mTestRenderEngine->setRenderLayers(mLayers); |
| ASSERT_NO_FATAL_FAILURE(mTestRenderEngine->drawLayers()); |
| ASSERT_NO_FATAL_FAILURE(mTestRenderEngine->checkColorBuffer(expectedColors)); |
| } |
| } |
| |
| TEST_P(GraphicsTransformCompositionTest, FLIP_V) { |
| for (ColorMode mode : mTestColorModes) { |
| EXPECT_TRUE(mComposerClient |
| ->setColorMode(getPrimaryDisplayId(), mode, RenderIntent::COLORIMETRIC) |
| .isOk()); |
| |
| bool isSupported; |
| ASSERT_NO_FATAL_FAILURE(isSupported = getHasReadbackBuffer()); |
| if (!isSupported) { |
| GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace"; |
| return; |
| } |
| ReadbackBuffer readbackBuffer(getPrimaryDisplayId(), mComposerClient, getDisplayWidth(), |
| getDisplayHeight(), mPixelFormat, mDataspace); |
| ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer()); |
| |
| mLayer->setTransform(Transform::FLIP_V); |
| mLayer->setDataspace(ReadbackHelper::getDataspaceForColorMode(mode)); |
| |
| std::vector<Color> expectedColors( |
| static_cast<size_t>(getDisplayWidth() * getDisplayHeight())); |
| ReadbackHelper::fillColorsArea(expectedColors, getDisplayWidth(), |
| {0, mSideLength / 2, mSideLength / 2, mSideLength}, RED); |
| ReadbackHelper::fillColorsArea(expectedColors, getDisplayWidth(), |
| {mSideLength / 2, 0, mSideLength, mSideLength / 2}, BLUE); |
| |
| writeLayers(mLayers); |
| ASSERT_TRUE(mReader.takeErrors().empty()); |
| mWriter->validateDisplay(getPrimaryDisplayId(), ComposerClientWriter::kNoTimestamp, |
| VtsComposerClient::kNoFrameIntervalNs); |
| execute(); |
| if (!mReader.takeChangedCompositionTypes(getPrimaryDisplayId()).empty()) { |
| GTEST_SUCCEED(); |
| return; |
| } |
| ASSERT_TRUE(mReader.takeErrors().empty()); |
| mWriter->presentDisplay(getPrimaryDisplayId()); |
| execute(); |
| ASSERT_TRUE(mReader.takeErrors().empty()); |
| ASSERT_NO_FATAL_FAILURE(readbackBuffer.checkReadbackBuffer(expectedColors)); |
| mTestRenderEngine->setRenderLayers(mLayers); |
| ASSERT_NO_FATAL_FAILURE(mTestRenderEngine->drawLayers()); |
| ASSERT_NO_FATAL_FAILURE(mTestRenderEngine->checkColorBuffer(expectedColors)); |
| } |
| } |
| |
| TEST_P(GraphicsTransformCompositionTest, ROT_180) { |
| for (ColorMode mode : mTestColorModes) { |
| EXPECT_TRUE(mComposerClient |
| ->setColorMode(getPrimaryDisplayId(), mode, RenderIntent::COLORIMETRIC) |
| .isOk()); |
| |
| bool isSupported; |
| ASSERT_NO_FATAL_FAILURE(isSupported = getHasReadbackBuffer()); |
| if (!isSupported) { |
| GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace"; |
| return; |
| } |
| ReadbackBuffer readbackBuffer(getPrimaryDisplayId(), mComposerClient, getDisplayWidth(), |
| getDisplayHeight(), mPixelFormat, mDataspace); |
| ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer()); |
| |
| mLayer->setTransform(Transform::ROT_180); |
| mLayer->setDataspace(ReadbackHelper::getDataspaceForColorMode(mode)); |
| |
| std::vector<Color> expectedColors( |
| static_cast<size_t>(getDisplayWidth() * getDisplayHeight())); |
| ReadbackHelper::fillColorsArea(expectedColors, getDisplayWidth(), |
| {mSideLength / 2, mSideLength / 2, mSideLength, mSideLength}, |
| RED); |
| ReadbackHelper::fillColorsArea(expectedColors, getDisplayWidth(), |
| {0, 0, mSideLength / 2, mSideLength / 2}, BLUE); |
| |
| writeLayers(mLayers); |
| ASSERT_TRUE(mReader.takeErrors().empty()); |
| mWriter->validateDisplay(getPrimaryDisplayId(), ComposerClientWriter::kNoTimestamp, |
| VtsComposerClient::kNoFrameIntervalNs); |
| execute(); |
| if (!mReader.takeChangedCompositionTypes(getPrimaryDisplayId()).empty()) { |
| GTEST_SUCCEED(); |
| return; |
| } |
| ASSERT_TRUE(mReader.takeErrors().empty()); |
| mWriter->presentDisplay(getPrimaryDisplayId()); |
| execute(); |
| ASSERT_TRUE(mReader.takeErrors().empty()); |
| ASSERT_NO_FATAL_FAILURE(readbackBuffer.checkReadbackBuffer(expectedColors)); |
| mTestRenderEngine->setRenderLayers(mLayers); |
| ASSERT_NO_FATAL_FAILURE(mTestRenderEngine->drawLayers()); |
| ASSERT_NO_FATAL_FAILURE(mTestRenderEngine->checkColorBuffer(expectedColors)); |
| } |
| } |
| |
| class GraphicsColorManagementCompositionTest |
| : public GraphicsCompositionTestBase, |
| public testing::WithParamInterface<std::tuple<std::string, Dataspace, Dataspace, Dataspace>> { |
| public: |
| void SetUp() override { |
| SetUpBase(std::get<0>(GetParam())); |
| // for some reason only sRGB reliably works |
| mTestColorModes.erase( |
| std::remove_if(mTestColorModes.begin(), mTestColorModes.end(), |
| [](ColorMode mode) { return mode != ColorMode::SRGB; }), |
| mTestColorModes.end()); |
| auto standard = std::get<1>(GetParam()); |
| auto transfer = std::get<2>(GetParam()); |
| auto range = std::get<3>(GetParam()); |
| |
| mLayerDataspace = static_cast<Dataspace>(static_cast<int32_t>(standard) | |
| static_cast<int32_t>(transfer) | |
| static_cast<int32_t>(range)); |
| ALOGD("Invoking test for dataspace: {%s, %s, %s}", toString(standard).c_str(), |
| toString(transfer).c_str(), toString(range).c_str()); |
| } |
| |
| void makeLayer() { |
| mLayer = std::make_shared<TestBufferLayer>( |
| mComposerClient, *mTestRenderEngine, getPrimaryDisplayId(), getDisplayWidth(), |
| getDisplayHeight(), common::PixelFormat::RGBA_8888, *mWriter); |
| mLayer->setDisplayFrame({0, 0, getDisplayWidth(), getDisplayHeight()}); |
| mLayer->setZOrder(10); |
| mLayer->setAlpha(1.f); |
| mLayer->setDataspace(mLayerDataspace); |
| } |
| |
| void fillColor(Color color) { |
| std::vector<Color> baseColors(static_cast<size_t>(getDisplayWidth() * getDisplayHeight())); |
| ReadbackHelper::fillColorsArea(baseColors, getDisplayWidth(), |
| common::Rect{.left = 0, |
| .top = 0, |
| .right = getDisplayWidth(), |
| .bottom = getDisplayHeight()}, |
| color); |
| ASSERT_NO_FATAL_FAILURE(mLayer->setBuffer(baseColors)); |
| } |
| |
| Dataspace mLayerDataspace; |
| std::shared_ptr<TestBufferLayer> mLayer; |
| }; |
| |
| TEST_P(GraphicsColorManagementCompositionTest, ColorConversion) { |
| for (ColorMode mode : mTestColorModes) { |
| EXPECT_TRUE(mComposerClient |
| ->setColorMode(getPrimaryDisplayId(), mode, RenderIntent::COLORIMETRIC) |
| .isOk()); |
| |
| bool isSupported; |
| ASSERT_NO_FATAL_FAILURE(isSupported = getHasReadbackBuffer()); |
| if (!isSupported) { |
| GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace"; |
| return; |
| } |
| |
| mClientCompositionDisplaySettings.outputDataspace = |
| static_cast<::android::ui::Dataspace>(mDataspace); |
| mTestRenderEngine->setDisplaySettings(mClientCompositionDisplaySettings); |
| |
| makeLayer(); |
| for (auto color : {LIGHT_RED, LIGHT_GREEN, LIGHT_BLUE}) { |
| ALOGD("Testing color: %f, %f, %f, %f with color mode: %d", color.r, color.g, color.b, |
| color.a, mode); |
| ReadbackBuffer readbackBuffer(getPrimaryDisplayId(), mComposerClient, getDisplayWidth(), |
| getDisplayHeight(), mPixelFormat, mDataspace); |
| ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer()); |
| fillColor(color); |
| writeLayers({mLayer}); |
| EXPECT_TRUE(mComposerClient->setPowerMode(getPrimaryDisplayId(), PowerMode::ON).isOk()); |
| |
| ASSERT_TRUE(mReader.takeErrors().empty()); |
| mWriter->validateDisplay(getPrimaryDisplayId(), ComposerClientWriter::kNoTimestamp, |
| VtsComposerClient::kNoFrameIntervalNs); |
| execute(); |
| if (!mReader.takeChangedCompositionTypes(getPrimaryDisplayId()).empty()) { |
| continue; |
| } |
| ASSERT_TRUE(mReader.takeErrors().empty()); |
| mWriter->presentDisplay(getPrimaryDisplayId()); |
| execute(); |
| ASSERT_TRUE(mReader.takeErrors().empty()); |
| |
| mTestRenderEngine->setRenderLayers({mLayer}); |
| ASSERT_NO_FATAL_FAILURE(mTestRenderEngine->drawLayers()); |
| ASSERT_NO_FATAL_FAILURE( |
| mTestRenderEngine->checkColorBuffer(readbackBuffer.getBuffer())); |
| } |
| } |
| } |
| |
| GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(GraphicsCompositionTest); |
| INSTANTIATE_TEST_SUITE_P( |
| PerInstance, GraphicsCompositionTest, |
| testing::ValuesIn(::android::getAidlHalInstanceNames(IComposer::descriptor)), |
| ::android::PrintInstanceNameToString); |
| |
| GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(GraphicsBlendModeCompositionTest); |
| INSTANTIATE_TEST_SUITE_P(BlendMode, GraphicsBlendModeCompositionTest, |
| testing::Combine(testing::ValuesIn(::android::getAidlHalInstanceNames( |
| IComposer::descriptor)), |
| testing::Values("0.2", "1.0"))); |
| |
| GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(GraphicsTransformCompositionTest); |
| INSTANTIATE_TEST_SUITE_P( |
| PerInstance, GraphicsTransformCompositionTest, |
| testing::ValuesIn(::android::getAidlHalInstanceNames(IComposer::descriptor)), |
| ::android::PrintInstanceNameToString); |
| |
| GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(GraphicsColorManagementCompositionTest); |
| INSTANTIATE_TEST_SUITE_P(PerInstance, GraphicsColorManagementCompositionTest, |
| testing::Combine(testing::ValuesIn(::android::getAidlHalInstanceNames( |
| IComposer::descriptor)), |
| // Only check sRGB, but verify that extended range |
| // doesn't trigger any gamma shifts |
| testing::Values(Dataspace::STANDARD_BT709), |
| testing::Values(Dataspace::TRANSFER_SRGB), |
| // Don't test limited range until we send YUV overlays |
| testing::Values(Dataspace::RANGE_FULL, |
| Dataspace::RANGE_EXTENDED))); |
| |
| } // namespace |
| } // namespace aidl::android::hardware::graphics::composer3::vts |