| /** |
| * 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 <android/binder_manager.h> |
| #include <composer-vts/include/ReadbackVts.h> |
| #include <composer-vts/include/RenderEngineVts.h> |
| #include <gtest/gtest.h> |
| #include <ui/GraphicBuffer.h> |
| #include <ui/GraphicBufferAllocator.h> |
| #include <ui/PixelFormat.h> |
| #include <ui/Rect.h> |
| #include "composer-vts/include/GraphicsComposerCallback.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) { |
| ndk::SpAIBinder binder(AServiceManager_waitForService(name.c_str())); |
| ASSERT_NE(binder, nullptr); |
| ASSERT_NO_FATAL_FAILURE(mComposer = IComposer::fromBinder(binder)); |
| ASSERT_NE(mComposer, nullptr); |
| ASSERT_NO_FATAL_FAILURE(mComposer->createClient(&mComposerClient)); |
| mComposerCallback = ::ndk::SharedRefBase::make<GraphicsComposerCallback>(); |
| mComposerClient->registerCallback(mComposerCallback); |
| |
| // assume the first display is primary and is never removed |
| mPrimaryDisplay = waitForFirstDisplay(); |
| |
| ASSERT_NO_FATAL_FAILURE(mInvalidDisplayId = GetInvalidDisplayId()); |
| |
| int32_t activeConfig; |
| EXPECT_TRUE(mComposerClient->getActiveConfig(mPrimaryDisplay, &activeConfig).isOk()); |
| EXPECT_TRUE(mComposerClient |
| ->getDisplayAttribute(mPrimaryDisplay, activeConfig, |
| DisplayAttribute::WIDTH, &mDisplayWidth) |
| .isOk()); |
| EXPECT_TRUE(mComposerClient |
| ->getDisplayAttribute(mPrimaryDisplay, activeConfig, |
| DisplayAttribute::HEIGHT, &mDisplayHeight) |
| .isOk()); |
| |
| setTestColorModes(); |
| |
| // explicitly disable vsync |
| EXPECT_TRUE(mComposerClient->setVsyncEnabled(mPrimaryDisplay, false).isOk()); |
| mComposerCallback->setVsyncAllowed(false); |
| |
| // set up gralloc |
| mGraphicBuffer = allocate(); |
| |
| ASSERT_NO_FATAL_FAILURE(mComposerClient->setPowerMode(mPrimaryDisplay, PowerMode::ON)); |
| |
| ASSERT_NO_FATAL_FAILURE( |
| mTestRenderEngine = std::unique_ptr<TestRenderEngine>(new TestRenderEngine( |
| ::android::renderengine::RenderEngineCreationArgs::Builder() |
| .setPixelFormat(static_cast<int>(common::PixelFormat::RGBA_8888)) |
| .setImageCacheSize(TestRenderEngine::sMaxFrameBufferAcquireBuffers) |
| .setUseColorManagerment(true) |
| .setEnableProtectedContext(false) |
| .setPrecacheToneMapperShaderOnly(false) |
| .setContextPriority(::android::renderengine::RenderEngine:: |
| ContextPriority::HIGH) |
| .build()))); |
| |
| ::android::renderengine::DisplaySettings clientCompositionDisplay; |
| clientCompositionDisplay.physicalDisplay = Rect(mDisplayWidth, mDisplayHeight); |
| clientCompositionDisplay.clip = clientCompositionDisplay.physicalDisplay; |
| |
| mTestRenderEngine->initGraphicBuffer( |
| static_cast<uint32_t>(mDisplayWidth), static_cast<uint32_t>(mDisplayHeight), 1, |
| 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(clientCompositionDisplay); |
| } |
| |
| void TearDown() override { |
| ASSERT_NO_FATAL_FAILURE(mComposerClient->setPowerMode(mPrimaryDisplay, PowerMode::OFF)); |
| const auto errors = mReader.takeErrors(); |
| ASSERT_TRUE(mReader.takeErrors().empty()); |
| |
| std::vector<int64_t> layers; |
| std::vector<Composition> types; |
| mReader.takeChangedCompositionTypes(mPrimaryDisplay, &layers, &types); |
| |
| ASSERT_TRUE(layers.empty()); |
| ASSERT_TRUE(types.empty()); |
| if (mComposerCallback != nullptr) { |
| EXPECT_EQ(0, mComposerCallback->getInvalidHotplugCount()); |
| EXPECT_EQ(0, mComposerCallback->getInvalidRefreshCount()); |
| EXPECT_EQ(0, mComposerCallback->getInvalidVsyncCount()); |
| } |
| } |
| |
| ::android::sp<::android::GraphicBuffer> allocate() { |
| return ::android::sp<::android::GraphicBuffer>::make( |
| mDisplayWidth, mDisplayHeight, ::android::PIXEL_FORMAT_RGBA_8888, |
| /*layerCount*/ 1, |
| static_cast<uint64_t>(static_cast<int>(common::BufferUsage::CPU_WRITE_OFTEN) | |
| static_cast<int>(common::BufferUsage::CPU_READ_OFTEN)), |
| "VtsHalGraphicsComposer3_ReadbackTest"); |
| } |
| |
| void writeLayers(const std::vector<std::shared_ptr<TestLayer>>& layers) { |
| for (auto layer : layers) { |
| layer->write(mWriter); |
| } |
| execute(); |
| } |
| |
| void execute() { |
| const auto& commands = mWriter.getPendingCommands(); |
| if (commands.empty()) { |
| mWriter.reset(); |
| return; |
| } |
| |
| std::vector<CommandResultPayload> results; |
| const auto status = mComposerClient->executeCommands(commands, &results); |
| ASSERT_TRUE(status.isOk()) << "executeCommands failed " << status.getDescription(); |
| |
| mReader.parse(results); |
| mWriter.reset(); |
| } |
| |
| bool getHasReadbackBuffer() { |
| ReadbackBufferAttributes readBackBufferAttributes; |
| const auto error = mComposerClient->getReadbackBufferAttributes(mPrimaryDisplay, |
| &readBackBufferAttributes); |
| mPixelFormat = readBackBufferAttributes.format; |
| mDataspace = readBackBufferAttributes.dataspace; |
| return error.isOk() && ReadbackHelper::readbackSupported(mPixelFormat, mDataspace); |
| } |
| |
| std::shared_ptr<IComposer> mComposer; |
| std::shared_ptr<IComposerClient> mComposerClient; |
| |
| std::shared_ptr<GraphicsComposerCallback> mComposerCallback; |
| // the first display and is assumed never to be removed |
| int64_t mPrimaryDisplay; |
| int64_t mInvalidDisplayId; |
| int32_t mDisplayWidth; |
| int32_t mDisplayHeight; |
| std::vector<ColorMode> mTestColorModes; |
| CommandWriterBase mWriter; |
| CommandReaderBase mReader; |
| ::android::sp<::android::GraphicBuffer> mGraphicBuffer; |
| std::unique_ptr<TestRenderEngine> mTestRenderEngine; |
| |
| common::PixelFormat mPixelFormat; |
| common::Dataspace mDataspace; |
| |
| static constexpr uint32_t kClientTargetSlotCount = 64; |
| |
| private: |
| int64_t waitForFirstDisplay() { |
| while (true) { |
| std::vector<int64_t> displays = mComposerCallback->getDisplays(); |
| if (displays.empty()) { |
| usleep(5 * 1000); |
| continue; |
| } |
| return displays[0]; |
| } |
| } |
| |
| void setTestColorModes() { |
| mTestColorModes.clear(); |
| std::vector<ColorMode> modes; |
| EXPECT_TRUE(mComposerClient->getColorModes(mPrimaryDisplay, &modes).isOk()); |
| |
| for (ColorMode mode : modes) { |
| if (std::find(ReadbackHelper::colorModes.begin(), ReadbackHelper::colorModes.end(), |
| mode) != ReadbackHelper::colorModes.end()) { |
| mTestColorModes.push_back(mode); |
| } |
| } |
| } |
| |
| // returns an invalid display id (one that has not been registered to a |
| // display. Currently assuming that a device will never have close to |
| // std::numeric_limit<uint64_t>::max() displays registered while running tests |
| int64_t GetInvalidDisplayId() { |
| int64_t id = std::numeric_limits<int64_t>::max(); |
| std::vector<int64_t> displays = mComposerCallback->getDisplays(); |
| while (id > 0) { |
| if (std::none_of(displays.begin(), displays.end(), |
| [&](const auto& display) { return id == display; })) { |
| return id; |
| } |
| id--; |
| } |
| |
| // Although 0 could be an invalid display, a return value of 0 |
| // from GetInvalidDisplayId means all other ids are in use, a condition which |
| // we are assuming a device will never have |
| EXPECT_NE(0, id); |
| return id; |
| } |
| }; |
| |
| class GraphicsCompositionTest : public GraphicsCompositionTestBase, |
| public testing::WithParamInterface<std::string> { |
| public: |
| void SetUp() override { SetUpBase(GetParam()); } |
| }; |
| |
| TEST_P(GraphicsCompositionTest, SingleSolidColorLayer) { |
| for (ColorMode mode : mTestColorModes) { |
| ASSERT_NO_FATAL_FAILURE( |
| mComposerClient->setColorMode(mPrimaryDisplay, mode, RenderIntent::COLORIMETRIC)); |
| |
| if (!getHasReadbackBuffer()) { |
| GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace"; |
| return; |
| } |
| |
| auto layer = std::make_shared<TestColorLayer>(mComposerClient, mPrimaryDisplay); |
| common::Rect coloredSquare({0, 0, mDisplayWidth, mDisplayHeight}); |
| 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>(mDisplayWidth * mDisplayHeight)); |
| ReadbackHelper::fillColorsArea(expectedColors, mDisplayWidth, coloredSquare, BLUE); |
| |
| ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mGraphicBuffer, |
| mDisplayWidth, mDisplayHeight, mPixelFormat, mDataspace); |
| ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer()); |
| |
| writeLayers(layers); |
| ASSERT_TRUE(mReader.takeErrors().empty()); |
| mWriter.validateDisplay(mPrimaryDisplay); |
| execute(); |
| // if hwc cannot handle and asks for composition change, |
| // just succeed the test |
| std::vector<int64_t> changedCompositionLayers; |
| std::vector<Composition> changedCompositionTypes; |
| mReader.takeChangedCompositionTypes(mPrimaryDisplay, &changedCompositionLayers, |
| &changedCompositionTypes); |
| if (!changedCompositionLayers.empty()) { |
| GTEST_SUCCEED(); |
| return; |
| } |
| ASSERT_TRUE(mReader.takeErrors().empty()); |
| mWriter.presentDisplay(mPrimaryDisplay); |
| 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) { |
| ASSERT_NO_FATAL_FAILURE( |
| mComposerClient->setColorMode(mPrimaryDisplay, mode, RenderIntent::COLORIMETRIC)); |
| |
| if (!getHasReadbackBuffer()) { |
| GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace"; |
| return; |
| } |
| |
| ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mGraphicBuffer, |
| mDisplayWidth, mDisplayHeight, mPixelFormat, mDataspace); |
| ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer()); |
| std::vector<Color> expectedColors(static_cast<size_t>(mDisplayWidth * mDisplayHeight)); |
| ReadbackHelper::fillColorsArea(expectedColors, mDisplayWidth, |
| {0, 0, mDisplayWidth, mDisplayHeight / 4}, RED); |
| ReadbackHelper::fillColorsArea(expectedColors, mDisplayWidth, |
| {0, mDisplayHeight / 4, mDisplayWidth, mDisplayHeight / 2}, |
| GREEN); |
| ReadbackHelper::fillColorsArea(expectedColors, mDisplayWidth, |
| {0, mDisplayHeight / 2, mDisplayWidth, mDisplayHeight}, |
| BLUE); |
| |
| auto layer = std::make_shared<TestBufferLayer>( |
| mComposerClient, mGraphicBuffer, *mTestRenderEngine, mPrimaryDisplay, mDisplayWidth, |
| mDisplayHeight, common::PixelFormat::RGBA_8888); |
| layer->setDisplayFrame({0, 0, mDisplayWidth, mDisplayHeight}); |
| layer->setZOrder(10); |
| layer->setDataspace(ReadbackHelper::getDataspaceForColorMode(mode), mWriter); |
| ASSERT_NO_FATAL_FAILURE(layer->setBuffer(expectedColors)); |
| |
| std::vector<std::shared_ptr<TestLayer>> layers = {layer}; |
| |
| writeLayers(layers); |
| ASSERT_TRUE(mReader.takeErrors().empty()); |
| mWriter.validateDisplay(mPrimaryDisplay); |
| execute(); |
| |
| std::vector<int64_t> changedCompositionLayers; |
| std::vector<Composition> changedCompositionTypes; |
| mReader.takeChangedCompositionTypes(mPrimaryDisplay, &changedCompositionLayers, |
| &changedCompositionTypes); |
| if (!changedCompositionLayers.empty()) { |
| GTEST_SUCCEED(); |
| return; |
| } |
| ASSERT_TRUE(mReader.takeErrors().empty()); |
| |
| mWriter.presentDisplay(mPrimaryDisplay); |
| 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) { |
| ASSERT_NO_FATAL_FAILURE( |
| mComposerClient->setColorMode(mPrimaryDisplay, mode, RenderIntent::COLORIMETRIC)); |
| |
| if (!getHasReadbackBuffer()) { |
| GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace"; |
| return; |
| } |
| |
| auto layer = std::make_shared<TestColorLayer>(mComposerClient, mPrimaryDisplay); |
| common::Rect coloredSquare({0, 0, mDisplayWidth, mDisplayHeight}); |
| layer->setColor(BLUE); |
| layer->setDisplayFrame(coloredSquare); |
| layer->setZOrder(10); |
| layer->write(mWriter); |
| |
| // This following buffer call should have no effect |
| uint64_t usage = |
| static_cast<uint64_t>(static_cast<uint64_t>(common::BufferUsage::CPU_READ_OFTEN) | |
| static_cast<uint64_t>(common::BufferUsage::CPU_WRITE_OFTEN)); |
| |
| mGraphicBuffer->reallocate(static_cast<uint32_t>(mDisplayWidth), |
| static_cast<uint32_t>(mDisplayHeight), 1, |
| static_cast<uint32_t>(common::PixelFormat::RGBA_8888), usage); |
| mWriter.setLayerBuffer(mPrimaryDisplay, layer->getLayer(), 0, mGraphicBuffer->handle, -1); |
| |
| // expected color for each pixel |
| std::vector<Color> expectedColors(static_cast<size_t>(mDisplayWidth * mDisplayHeight)); |
| ReadbackHelper::fillColorsArea(expectedColors, mDisplayWidth, coloredSquare, BLUE); |
| |
| ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mGraphicBuffer, |
| mDisplayWidth, mDisplayHeight, mPixelFormat, mDataspace); |
| ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer()); |
| |
| mWriter.validateDisplay(mPrimaryDisplay); |
| execute(); |
| |
| std::vector<int64_t> changedCompositionLayers; |
| std::vector<Composition> changedCompositionTypes; |
| mReader.takeChangedCompositionTypes(mPrimaryDisplay, &changedCompositionLayers, |
| &changedCompositionTypes); |
| if (!changedCompositionLayers.empty()) { |
| GTEST_SUCCEED(); |
| return; |
| } |
| ASSERT_TRUE(mReader.takeErrors().empty()); |
| mWriter.presentDisplay(mPrimaryDisplay); |
| execute(); |
| ASSERT_TRUE(mReader.takeErrors().empty()); |
| |
| ASSERT_NO_FATAL_FAILURE(readbackBuffer.checkReadbackBuffer(expectedColors)); |
| } |
| } |
| |
| TEST_P(GraphicsCompositionTest, SetReadbackBuffer) { |
| if (!getHasReadbackBuffer()) { |
| GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace"; |
| return; |
| } |
| |
| ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mGraphicBuffer, mDisplayWidth, |
| mDisplayHeight, mPixelFormat, mDataspace); |
| |
| ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer()); |
| } |
| |
| TEST_P(GraphicsCompositionTest, SetReadbackBufferBadDisplay) { |
| if (!getHasReadbackBuffer()) { |
| GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace"; |
| return; |
| } |
| |
| ASSERT_NE(nullptr, mGraphicBuffer); |
| ASSERT_EQ(::android::OK, mGraphicBuffer->initCheck()); |
| aidl::android::hardware::common::NativeHandle bufferHandle = |
| ::android::dupToAidl(mGraphicBuffer->handle); |
| ::ndk::ScopedFileDescriptor fence = ::ndk::ScopedFileDescriptor(-1); |
| |
| const auto error = mComposerClient->setReadbackBuffer(mInvalidDisplayId, bufferHandle, fence); |
| |
| EXPECT_FALSE(error.isOk()); |
| ASSERT_EQ(IComposerClient::EX_BAD_DISPLAY, error.getServiceSpecificError()); |
| } |
| |
| TEST_P(GraphicsCompositionTest, SetReadbackBufferBadParameter) { |
| if (!getHasReadbackBuffer()) { |
| GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace"; |
| return; |
| } |
| |
| aidl::android::hardware::common::NativeHandle bufferHandle = ::android::dupToAidl(nullptr); |
| ndk::ScopedFileDescriptor releaseFence = ndk::ScopedFileDescriptor(-1); |
| const auto error = |
| mComposerClient->setReadbackBuffer(mPrimaryDisplay, bufferHandle, releaseFence); |
| |
| EXPECT_FALSE(error.isOk()); |
| ASSERT_EQ(IComposerClient::EX_BAD_PARAMETER, error.getServiceSpecificError()); |
| } |
| |
| TEST_P(GraphicsCompositionTest, GetReadbackBufferFenceInactive) { |
| if (!getHasReadbackBuffer()) { |
| GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace"; |
| return; |
| } |
| |
| ndk::ScopedFileDescriptor releaseFence; |
| const auto error = mComposerClient->getReadbackBufferFence(mPrimaryDisplay, &releaseFence); |
| |
| EXPECT_TRUE(error.isOk()); |
| EXPECT_EQ(IComposerClient::EX_UNSUPPORTED, error.getServiceSpecificError()); |
| } |
| |
| TEST_P(GraphicsCompositionTest, ClientComposition) { |
| EXPECT_TRUE(mComposerClient->setClientTargetSlotCount(mPrimaryDisplay, kClientTargetSlotCount) |
| .isOk()); |
| |
| for (ColorMode mode : mTestColorModes) { |
| EXPECT_TRUE(mComposerClient->setColorMode(mPrimaryDisplay, mode, RenderIntent::COLORIMETRIC) |
| .isOk()); |
| |
| if (!getHasReadbackBuffer()) { |
| GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace"; |
| return; |
| } |
| |
| std::vector<Color> expectedColors(static_cast<size_t>(mDisplayWidth * mDisplayHeight)); |
| ReadbackHelper::fillColorsArea(expectedColors, mDisplayWidth, |
| {0, 0, mDisplayWidth, mDisplayHeight / 4}, RED); |
| ReadbackHelper::fillColorsArea(expectedColors, mDisplayWidth, |
| {0, mDisplayHeight / 4, mDisplayWidth, mDisplayHeight / 2}, |
| GREEN); |
| ReadbackHelper::fillColorsArea(expectedColors, mDisplayWidth, |
| {0, mDisplayHeight / 2, mDisplayWidth, mDisplayHeight}, |
| BLUE); |
| |
| auto layer = std::make_shared<TestBufferLayer>( |
| mComposerClient, mGraphicBuffer, *mTestRenderEngine, mPrimaryDisplay, mDisplayWidth, |
| mDisplayHeight, PixelFormat::RGBA_FP16); |
| layer->setDisplayFrame({0, 0, mDisplayWidth, mDisplayHeight}); |
| layer->setZOrder(10); |
| layer->setDataspace(ReadbackHelper::getDataspaceForColorMode(mode), mWriter); |
| |
| std::vector<std::shared_ptr<TestLayer>> layers = {layer}; |
| |
| ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mGraphicBuffer, |
| mDisplayWidth, mDisplayHeight, mPixelFormat, mDataspace); |
| ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer()); |
| writeLayers(layers); |
| ASSERT_TRUE(mReader.takeErrors().empty()); |
| mWriter.validateDisplay(mPrimaryDisplay); |
| execute(); |
| |
| std::vector<int64_t> changedCompositionLayers; |
| std::vector<Composition> changedCompositionTypes; |
| mReader.takeChangedCompositionTypes(mPrimaryDisplay, &changedCompositionLayers, |
| &changedCompositionTypes); |
| if (!changedCompositionLayers.empty()) { |
| ASSERT_EQ(1, changedCompositionLayers.size()); |
| ASSERT_EQ(1, changedCompositionTypes.size()); |
| ASSERT_EQ(Composition::CLIENT, changedCompositionTypes[0]); |
| |
| 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, mDisplayWidth, mDisplayHeight}; |
| |
| // create client target buffer |
| mGraphicBuffer->reallocate(layer->getWidth(), layer->getHeight(), |
| static_cast<int32_t>(common::PixelFormat::RGBA_8888), |
| layer->getLayerCount(), clientUsage); |
| |
| ASSERT_NE(nullptr, mGraphicBuffer->handle); |
| |
| void* clientBufData; |
| mGraphicBuffer->lock(clientUsage, layer->getAccessRegion(), &clientBufData); |
| |
| ASSERT_NO_FATAL_FAILURE( |
| ReadbackHelper::fillBuffer(layer->getWidth(), layer->getHeight(), |
| static_cast<uint32_t>(mGraphicBuffer->stride), |
| clientBufData, clientFormat, expectedColors)); |
| EXPECT_EQ(::android::OK, mGraphicBuffer->unlock()); |
| |
| ndk::ScopedFileDescriptor fenceHandle; |
| EXPECT_TRUE( |
| mComposerClient->getReadbackBufferFence(mPrimaryDisplay, &fenceHandle).isOk()); |
| |
| layer->setToClientComposition(mWriter); |
| mWriter.acceptDisplayChanges(mPrimaryDisplay); |
| mWriter.setClientTarget(mPrimaryDisplay, 0, mGraphicBuffer->handle, fenceHandle.get(), |
| clientDataspace, std::vector<common::Rect>(1, damage)); |
| execute(); |
| mReader.takeChangedCompositionTypes(mPrimaryDisplay, &changedCompositionLayers, |
| &changedCompositionTypes); |
| ASSERT_TRUE(changedCompositionLayers.empty()); |
| } |
| ASSERT_TRUE(mReader.takeErrors().empty()); |
| |
| mWriter.presentDisplay(mPrimaryDisplay); |
| execute(); |
| |
| ASSERT_TRUE(mReader.takeErrors().empty()); |
| |
| ASSERT_NO_FATAL_FAILURE(readbackBuffer.checkReadbackBuffer(expectedColors)); |
| } |
| } |
| |
| TEST_P(GraphicsCompositionTest, DeviceAndClientComposition) { |
| ASSERT_NO_FATAL_FAILURE( |
| mComposerClient->setClientTargetSlotCount(mPrimaryDisplay, kClientTargetSlotCount)); |
| |
| for (ColorMode mode : mTestColorModes) { |
| ASSERT_NO_FATAL_FAILURE( |
| mComposerClient->setColorMode(mPrimaryDisplay, mode, RenderIntent::COLORIMETRIC)); |
| |
| if (!getHasReadbackBuffer()) { |
| GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace"; |
| return; |
| } |
| |
| std::vector<Color> expectedColors(static_cast<size_t>(mDisplayWidth * mDisplayHeight)); |
| ReadbackHelper::fillColorsArea(expectedColors, mDisplayWidth, |
| {0, 0, mDisplayWidth, mDisplayHeight / 2}, GREEN); |
| ReadbackHelper::fillColorsArea(expectedColors, mDisplayWidth, |
| {0, mDisplayHeight / 2, mDisplayWidth, mDisplayHeight}, RED); |
| |
| ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mGraphicBuffer, |
| mDisplayWidth, mDisplayHeight, mPixelFormat, mDataspace); |
| ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer()); |
| |
| auto deviceLayer = std::make_shared<TestBufferLayer>( |
| mComposerClient, mGraphicBuffer, *mTestRenderEngine, mPrimaryDisplay, mDisplayWidth, |
| mDisplayHeight / 2, PixelFormat::RGBA_8888); |
| 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), mWriter); |
| 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 = mDisplayWidth; |
| int32_t clientHeight = mDisplayHeight / 2; |
| |
| auto clientLayer = std::make_shared<TestBufferLayer>( |
| mComposerClient, mGraphicBuffer, *mTestRenderEngine, mPrimaryDisplay, clientWidth, |
| clientHeight, PixelFormat::RGBA_FP16, Composition::DEVICE); |
| common::Rect clientFrame = {0, mDisplayHeight / 2, mDisplayWidth, mDisplayHeight}; |
| clientLayer->setDisplayFrame(clientFrame); |
| clientLayer->setZOrder(0); |
| clientLayer->write(mWriter); |
| mWriter.validateDisplay(mPrimaryDisplay); |
| execute(); |
| |
| std::vector<int64_t> changedCompositionLayers; |
| std::vector<Composition> changedCompositionTypes; |
| mReader.takeChangedCompositionTypes(mPrimaryDisplay, &changedCompositionLayers, |
| &changedCompositionTypes); |
| if (changedCompositionTypes.size() != 1) { |
| continue; |
| } |
| // create client target buffer |
| ASSERT_EQ(Composition::CLIENT, changedCompositionTypes[0]); |
| mGraphicBuffer->reallocate(static_cast<uint32_t>(mDisplayWidth), |
| static_cast<uint32_t>(mDisplayHeight), |
| static_cast<int32_t>(common::PixelFormat::RGBA_8888), |
| clientLayer->getLayerCount(), clientUsage); |
| ASSERT_NE(nullptr, mGraphicBuffer->handle); |
| |
| void* clientBufData; |
| mGraphicBuffer->lock(clientUsage, {0, 0, mDisplayWidth, mDisplayHeight}, &clientBufData); |
| |
| std::vector<Color> clientColors(static_cast<size_t>(mDisplayWidth * mDisplayHeight)); |
| ReadbackHelper::fillColorsArea(clientColors, mDisplayWidth, clientFrame, RED); |
| ASSERT_NO_FATAL_FAILURE(ReadbackHelper::fillBuffer( |
| static_cast<uint32_t>(mDisplayWidth), static_cast<uint32_t>(mDisplayHeight), |
| mGraphicBuffer->getStride(), clientBufData, clientFormat, clientColors)); |
| EXPECT_EQ(::android::OK, mGraphicBuffer->unlock()); |
| |
| ndk::ScopedFileDescriptor fenceHandle; |
| EXPECT_TRUE(mComposerClient->getReadbackBufferFence(mPrimaryDisplay, &fenceHandle).isOk()); |
| |
| clientLayer->setToClientComposition(mWriter); |
| mWriter.acceptDisplayChanges(mPrimaryDisplay); |
| mWriter.setClientTarget(mPrimaryDisplay, 0, mGraphicBuffer->handle, fenceHandle.get(), |
| clientDataspace, std::vector<common::Rect>(1, clientFrame)); |
| execute(); |
| mReader.takeChangedCompositionTypes(mPrimaryDisplay, &changedCompositionLayers, |
| &changedCompositionTypes); |
| ASSERT_EQ(0, changedCompositionLayers.size()); |
| ASSERT_TRUE(mReader.takeErrors().empty()); |
| |
| mWriter.presentDisplay(mPrimaryDisplay); |
| execute(); |
| ASSERT_TRUE(mReader.takeErrors().empty()); |
| ASSERT_NO_FATAL_FAILURE(readbackBuffer.checkReadbackBuffer(expectedColors)); |
| } |
| } |
| |
| TEST_P(GraphicsCompositionTest, SetLayerDamage) { |
| for (ColorMode mode : mTestColorModes) { |
| ASSERT_NO_FATAL_FAILURE( |
| mComposerClient->setColorMode(mPrimaryDisplay, mode, RenderIntent::COLORIMETRIC)); |
| |
| if (!getHasReadbackBuffer()) { |
| GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace"; |
| return; |
| } |
| |
| common::Rect redRect = {0, 0, mDisplayWidth / 4, mDisplayHeight / 4}; |
| |
| std::vector<Color> expectedColors(static_cast<size_t>(mDisplayWidth * mDisplayHeight)); |
| ReadbackHelper::fillColorsArea(expectedColors, mDisplayWidth, redRect, RED); |
| |
| auto layer = std::make_shared<TestBufferLayer>( |
| mComposerClient, mGraphicBuffer, *mTestRenderEngine, mPrimaryDisplay, mDisplayWidth, |
| mDisplayHeight, PixelFormat::RGBA_8888); |
| layer->setDisplayFrame({0, 0, mDisplayWidth, mDisplayHeight}); |
| layer->setZOrder(10); |
| layer->setDataspace(ReadbackHelper::getDataspaceForColorMode(mode), mWriter); |
| ASSERT_NO_FATAL_FAILURE(layer->setBuffer(expectedColors)); |
| |
| std::vector<std::shared_ptr<TestLayer>> layers = {layer}; |
| |
| ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mGraphicBuffer, |
| mDisplayWidth, mDisplayHeight, mPixelFormat, mDataspace); |
| ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer()); |
| |
| writeLayers(layers); |
| ASSERT_TRUE(mReader.takeErrors().empty()); |
| mWriter.validateDisplay(mPrimaryDisplay); |
| execute(); |
| std::vector<int64_t> changedCompositionLayers; |
| std::vector<Composition> changedCompositionTypes; |
| mReader.takeChangedCompositionTypes(mPrimaryDisplay, &changedCompositionLayers, |
| &changedCompositionTypes); |
| if (!changedCompositionLayers.empty()) { |
| GTEST_SUCCEED(); |
| return; |
| } |
| ASSERT_TRUE(mReader.takeErrors().empty()); |
| mWriter.presentDisplay(mPrimaryDisplay); |
| execute(); |
| ASSERT_TRUE(mReader.takeErrors().empty()); |
| |
| ASSERT_NO_FATAL_FAILURE(readbackBuffer.checkReadbackBuffer(expectedColors)); |
| |
| // update surface damage and recheck |
| redRect = {mDisplayWidth / 4, mDisplayHeight / 4, mDisplayWidth / 2, mDisplayHeight / 2}; |
| ReadbackHelper::clearColors(expectedColors, mDisplayWidth, mDisplayHeight, mDisplayWidth); |
| ReadbackHelper::fillColorsArea(expectedColors, mDisplayWidth, redRect, RED); |
| |
| ASSERT_NO_FATAL_FAILURE(layer->fillBuffer(expectedColors)); |
| layer->setSurfaceDamage( |
| std::vector<common::Rect>(1, {0, 0, mDisplayWidth / 2, mDisplayWidth / 2})); |
| |
| ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer()); |
| |
| writeLayers(layers); |
| ASSERT_TRUE(mReader.takeErrors().empty()); |
| mWriter.validateDisplay(mPrimaryDisplay); |
| execute(); |
| ASSERT_TRUE(mReader.takeErrors().empty()); |
| mReader.takeChangedCompositionTypes(mPrimaryDisplay, &changedCompositionLayers, |
| &changedCompositionTypes); |
| ASSERT_TRUE(changedCompositionLayers.empty()); |
| ASSERT_TRUE(changedCompositionTypes.empty()); |
| mWriter.presentDisplay(mPrimaryDisplay); |
| execute(); |
| ASSERT_TRUE(mReader.takeErrors().empty()); |
| |
| ASSERT_NO_FATAL_FAILURE(readbackBuffer.checkReadbackBuffer(expectedColors)); |
| } |
| } |
| |
| TEST_P(GraphicsCompositionTest, SetLayerPlaneAlpha) { |
| for (ColorMode mode : mTestColorModes) { |
| ASSERT_NO_FATAL_FAILURE( |
| mComposerClient->setColorMode(mPrimaryDisplay, mode, RenderIntent::COLORIMETRIC)); |
| |
| if (!getHasReadbackBuffer()) { |
| GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace"; |
| return; |
| } |
| |
| auto layer = std::make_shared<TestColorLayer>(mComposerClient, mPrimaryDisplay); |
| layer->setColor(RED); |
| layer->setDisplayFrame({0, 0, mDisplayWidth, mDisplayHeight}); |
| layer->setZOrder(10); |
| layer->setAlpha(0); |
| layer->setBlendMode(BlendMode::PREMULTIPLIED); |
| |
| std::vector<std::shared_ptr<TestLayer>> layers = {layer}; |
| |
| ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mGraphicBuffer, |
| mDisplayWidth, mDisplayHeight, mPixelFormat, mDataspace); |
| |
| ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer()); |
| |
| writeLayers(layers); |
| ASSERT_TRUE(mReader.takeErrors().empty()); |
| mWriter.validateDisplay(mPrimaryDisplay); |
| execute(); |
| std::vector<int64_t> changedCompositionLayers; |
| std::vector<Composition> changedCompositionTypes; |
| mReader.takeChangedCompositionTypes(mPrimaryDisplay, &changedCompositionLayers, |
| &changedCompositionTypes); |
| if (!changedCompositionLayers.empty()) { |
| GTEST_SUCCEED(); |
| return; |
| } |
| ASSERT_TRUE(mReader.takeErrors().empty()); |
| |
| mWriter.presentDisplay(mPrimaryDisplay); |
| execute(); |
| ASSERT_TRUE(mReader.takeErrors().empty()); |
| |
| std::vector<Color> expectedColors(static_cast<size_t>(mDisplayWidth * mDisplayHeight)); |
| |
| 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) { |
| ASSERT_NO_FATAL_FAILURE( |
| mComposerClient->setColorMode(mPrimaryDisplay, mode, RenderIntent::COLORIMETRIC)); |
| |
| if (!getHasReadbackBuffer()) { |
| GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace"; |
| return; |
| } |
| |
| std::vector<Color> expectedColors(static_cast<size_t>(mDisplayWidth * mDisplayHeight)); |
| ReadbackHelper::fillColorsArea(expectedColors, mDisplayWidth, |
| {0, 0, mDisplayWidth, mDisplayHeight / 4}, RED); |
| ReadbackHelper::fillColorsArea(expectedColors, mDisplayWidth, |
| {0, mDisplayHeight / 2, mDisplayWidth, mDisplayHeight}, |
| BLUE); |
| |
| auto layer = std::make_shared<TestBufferLayer>( |
| mComposerClient, mGraphicBuffer, *mTestRenderEngine, mPrimaryDisplay, mDisplayWidth, |
| mDisplayHeight, PixelFormat::RGBA_8888); |
| layer->setDisplayFrame({0, 0, mDisplayWidth, mDisplayHeight}); |
| layer->setZOrder(10); |
| layer->setDataspace(ReadbackHelper::getDataspaceForColorMode(mode), mWriter); |
| layer->setSourceCrop({0, static_cast<float>(mDisplayHeight / 2), |
| static_cast<float>(mDisplayWidth), |
| static_cast<float>(mDisplayHeight)}); |
| ASSERT_NO_FATAL_FAILURE(layer->setBuffer(expectedColors)); |
| |
| std::vector<std::shared_ptr<TestLayer>> layers = {layer}; |
| |
| // update expected colors to match crop |
| ReadbackHelper::fillColorsArea(expectedColors, mDisplayWidth, |
| {0, 0, mDisplayWidth, mDisplayHeight}, BLUE); |
| ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mGraphicBuffer, |
| mDisplayWidth, mDisplayHeight, mPixelFormat, mDataspace); |
| ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer()); |
| writeLayers(layers); |
| ASSERT_TRUE(mReader.takeErrors().empty()); |
| mWriter.validateDisplay(mPrimaryDisplay); |
| execute(); |
| std::vector<int64_t> changedCompositionLayers; |
| std::vector<Composition> changedCompositionTypes; |
| mReader.takeChangedCompositionTypes(mPrimaryDisplay, &changedCompositionLayers, |
| &changedCompositionTypes); |
| if (!changedCompositionLayers.empty()) { |
| GTEST_SUCCEED(); |
| return; |
| } |
| ASSERT_TRUE(mReader.takeErrors().empty()); |
| mWriter.presentDisplay(mPrimaryDisplay); |
| 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) { |
| ASSERT_NO_FATAL_FAILURE( |
| mComposerClient->setColorMode(mPrimaryDisplay, mode, RenderIntent::COLORIMETRIC)); |
| |
| if (!getHasReadbackBuffer()) { |
| GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace"; |
| return; |
| } |
| |
| common::Rect redRect = {0, 0, mDisplayWidth, mDisplayHeight / 2}; |
| common::Rect blueRect = {0, mDisplayHeight / 4, mDisplayWidth, mDisplayHeight}; |
| auto redLayer = std::make_shared<TestColorLayer>(mComposerClient, mPrimaryDisplay); |
| redLayer->setColor(RED); |
| redLayer->setDisplayFrame(redRect); |
| |
| auto blueLayer = std::make_shared<TestColorLayer>(mComposerClient, mPrimaryDisplay); |
| 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>(mDisplayWidth * mDisplayHeight)); |
| |
| // red in front of blue |
| redLayer->setZOrder(10); |
| |
| // fill blue first so that red will overwrite on overlap |
| ReadbackHelper::fillColorsArea(expectedColors, mDisplayWidth, blueRect, BLUE); |
| ReadbackHelper::fillColorsArea(expectedColors, mDisplayWidth, redRect, RED); |
| |
| ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mGraphicBuffer, |
| mDisplayWidth, mDisplayHeight, mPixelFormat, mDataspace); |
| ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer()); |
| |
| writeLayers(layers); |
| ASSERT_TRUE(mReader.takeErrors().empty()); |
| mWriter.validateDisplay(mPrimaryDisplay); |
| execute(); |
| std::vector<int64_t> changedCompositionLayers; |
| std::vector<Composition> changedCompositionTypes; |
| mReader.takeChangedCompositionTypes(mPrimaryDisplay, &changedCompositionLayers, |
| &changedCompositionTypes); |
| if (!changedCompositionLayers.empty()) { |
| GTEST_SUCCEED(); |
| return; |
| } |
| mWriter.presentDisplay(mPrimaryDisplay); |
| execute(); |
| ASSERT_TRUE(mReader.takeErrors().empty()); |
| |
| ASSERT_NO_FATAL_FAILURE(readbackBuffer.checkReadbackBuffer(expectedColors)); |
| |
| redLayer->setZOrder(1); |
| ReadbackHelper::clearColors(expectedColors, mDisplayWidth, mDisplayHeight, mDisplayWidth); |
| ReadbackHelper::fillColorsArea(expectedColors, mDisplayWidth, redRect, RED); |
| ReadbackHelper::fillColorsArea(expectedColors, mDisplayWidth, blueRect, BLUE); |
| |
| ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer()); |
| |
| writeLayers(layers); |
| ASSERT_TRUE(mReader.takeErrors().empty()); |
| mWriter.validateDisplay(mPrimaryDisplay); |
| execute(); |
| mReader.takeChangedCompositionTypes(mPrimaryDisplay, &changedCompositionLayers, |
| &changedCompositionTypes); |
| ASSERT_TRUE(changedCompositionLayers.empty()); |
| ASSERT_TRUE(changedCompositionTypes.empty()); |
| ASSERT_TRUE(mReader.takeErrors().empty()); |
| mWriter.presentDisplay(mPrimaryDisplay); |
| 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())); |
| 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>(mDisplayWidth * mDisplayHeight)); |
| ReadbackHelper::fillColorsArea(topLayerPixelColors, mDisplayWidth, |
| {0, 0, mDisplayWidth, mDisplayHeight}, mTopLayerColor); |
| |
| auto backgroundLayer = std::make_shared<TestColorLayer>(mComposerClient, mPrimaryDisplay); |
| backgroundLayer->setDisplayFrame({0, 0, mDisplayWidth, mDisplayHeight}); |
| backgroundLayer->setZOrder(0); |
| backgroundLayer->setColor(mBackgroundColor); |
| |
| auto layer = std::make_shared<TestBufferLayer>( |
| mComposerClient, mGraphicBuffer, *mTestRenderEngine, mPrimaryDisplay, mDisplayWidth, |
| mDisplayHeight, PixelFormat::RGBA_8888); |
| layer->setDisplayFrame({0, 0, mDisplayWidth, mDisplayHeight}); |
| layer->setZOrder(10); |
| layer->setDataspace(Dataspace::UNKNOWN, mWriter); |
| 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, mDisplayWidth, mDisplayHeight, mDisplayWidth); |
| |
| auto layer = mLayers[1]; |
| BlendMode blendMode = layer->getBlendMode(); |
| float alpha = mTopLayerColor.a / 255.0f * layer->getAlpha(); |
| if (blendMode == BlendMode::NONE) { |
| for (auto& expectedColor : expectedColors) { |
| expectedColor.r = mTopLayerColor.r * static_cast<int8_t>(layer->getAlpha()); |
| expectedColor.g = mTopLayerColor.g * static_cast<int8_t>(layer->getAlpha()); |
| expectedColor.b = mTopLayerColor.b * static_cast<int8_t>(layer->getAlpha()); |
| expectedColor.a = static_cast<int8_t>(alpha * 255.0); |
| } |
| } else if (blendMode == BlendMode::PREMULTIPLIED) { |
| for (auto& expectedColor : expectedColors) { |
| expectedColor.r = static_cast<int8_t>( |
| mTopLayerColor.r * static_cast<int8_t>(layer->getAlpha()) + |
| mBackgroundColor.r * (1.0 - alpha)); |
| expectedColor.g = static_cast<int8_t>(mTopLayerColor.g * layer->getAlpha() + |
| mBackgroundColor.g * (1.0 - alpha)); |
| expectedColor.b = static_cast<int8_t>(mTopLayerColor.b * layer->getAlpha() + |
| mBackgroundColor.b * (1.0 - alpha)); |
| expectedColor.a = static_cast<int8_t>(alpha + mBackgroundColor.a * (1.0 - alpha)); |
| } |
| } else if (blendMode == BlendMode::COVERAGE) { |
| for (auto& expectedColor : expectedColors) { |
| expectedColor.r = static_cast<int8_t>(mTopLayerColor.r * alpha + |
| mBackgroundColor.r * (1.0 - alpha)); |
| expectedColor.g = static_cast<int8_t>(mTopLayerColor.g * alpha + |
| mBackgroundColor.g * (1.0 - alpha)); |
| expectedColor.b = static_cast<int8_t>(mTopLayerColor.b * alpha + |
| mBackgroundColor.b * (1.0 - alpha)); |
| expectedColor.a = static_cast<int8_t>(mTopLayerColor.a * alpha + |
| mBackgroundColor.a * (1.0 - alpha)); |
| } |
| } |
| } |
| |
| protected: |
| std::vector<std::shared_ptr<TestLayer>> mLayers; |
| Color mBackgroundColor; |
| Color mTopLayerColor; |
| }; |
| |
| TEST_P(GraphicsBlendModeCompositionTest, None) { |
| for (ColorMode mode : mTestColorModes) { |
| ASSERT_NO_FATAL_FAILURE( |
| mComposerClient->setColorMode(mPrimaryDisplay, mode, RenderIntent::COLORIMETRIC)); |
| |
| if (!getHasReadbackBuffer()) { |
| GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace"; |
| return; |
| } |
| |
| std::vector<Color> expectedColors(static_cast<size_t>(mDisplayWidth * mDisplayHeight)); |
| |
| setBackgroundColor(BLACK); |
| setTopLayerColor(TRANSLUCENT_RED); |
| setUpLayers(BlendMode::NONE); |
| setExpectedColors(expectedColors); |
| |
| ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mGraphicBuffer, |
| mDisplayWidth, mDisplayHeight, mPixelFormat, mDataspace); |
| ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer()); |
| writeLayers(mLayers); |
| ASSERT_TRUE(mReader.takeErrors().empty()); |
| mWriter.validateDisplay(mPrimaryDisplay); |
| execute(); |
| std::vector<int64_t> changedCompositionLayers; |
| std::vector<Composition> changedCompositionTypes; |
| mReader.takeChangedCompositionTypes(mPrimaryDisplay, &changedCompositionLayers, |
| &changedCompositionTypes); |
| if (!changedCompositionLayers.empty()) { |
| GTEST_SUCCEED(); |
| return; |
| } |
| ASSERT_TRUE(mReader.takeErrors().empty()); |
| mWriter.presentDisplay(mPrimaryDisplay); |
| 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) { |
| ASSERT_NO_FATAL_FAILURE( |
| mComposerClient->setColorMode(mPrimaryDisplay, mode, RenderIntent::COLORIMETRIC)); |
| |
| if (!getHasReadbackBuffer()) { |
| GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace"; |
| return; |
| } |
| |
| std::vector<Color> expectedColors(static_cast<size_t>(mDisplayWidth * mDisplayHeight)); |
| |
| setBackgroundColor(BLACK); |
| setTopLayerColor(TRANSLUCENT_RED); |
| |
| setUpLayers(BlendMode::COVERAGE); |
| setExpectedColors(expectedColors); |
| |
| ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mGraphicBuffer, |
| mDisplayWidth, mDisplayHeight, mPixelFormat, mDataspace); |
| ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer()); |
| writeLayers(mLayers); |
| ASSERT_TRUE(mReader.takeErrors().empty()); |
| mWriter.validateDisplay(mPrimaryDisplay); |
| execute(); |
| std::vector<int64_t> changedCompositionLayers; |
| std::vector<Composition> changedCompositionTypes; |
| mReader.takeChangedCompositionTypes(mPrimaryDisplay, &changedCompositionLayers, |
| &changedCompositionTypes); |
| if (!changedCompositionLayers.empty()) { |
| GTEST_SUCCEED(); |
| return; |
| } |
| ASSERT_TRUE(mReader.takeErrors().empty()); |
| mWriter.presentDisplay(mPrimaryDisplay); |
| execute(); |
| ASSERT_TRUE(mReader.takeErrors().empty()); |
| ASSERT_NO_FATAL_FAILURE(readbackBuffer.checkReadbackBuffer(expectedColors)); |
| } |
| } |
| |
| TEST_P(GraphicsBlendModeCompositionTest, Premultiplied) { |
| for (ColorMode mode : mTestColorModes) { |
| ASSERT_NO_FATAL_FAILURE( |
| mComposerClient->setColorMode(mPrimaryDisplay, mode, RenderIntent::COLORIMETRIC)); |
| |
| if (!getHasReadbackBuffer()) { |
| GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace"; |
| return; |
| } |
| |
| std::vector<Color> expectedColors(static_cast<size_t>(mDisplayWidth * mDisplayHeight)); |
| |
| setBackgroundColor(BLACK); |
| setTopLayerColor(TRANSLUCENT_RED); |
| setUpLayers(BlendMode::PREMULTIPLIED); |
| setExpectedColors(expectedColors); |
| |
| ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mGraphicBuffer, |
| mDisplayWidth, mDisplayHeight, mPixelFormat, mDataspace); |
| ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer()); |
| writeLayers(mLayers); |
| ASSERT_TRUE(mReader.takeErrors().empty()); |
| mWriter.validateDisplay(mPrimaryDisplay); |
| execute(); |
| std::vector<int64_t> changedCompositionLayers; |
| std::vector<Composition> changedCompositionTypes; |
| mReader.takeChangedCompositionTypes(mPrimaryDisplay, &changedCompositionLayers, |
| &changedCompositionTypes); |
| if (!changedCompositionLayers.empty()) { |
| GTEST_SUCCEED(); |
| return; |
| } |
| ASSERT_TRUE(mReader.takeErrors().empty()); |
| mWriter.presentDisplay(mPrimaryDisplay); |
| 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, mPrimaryDisplay); |
| backgroundLayer->setColor({0, 0, 0, 0}); |
| backgroundLayer->setDisplayFrame({0, 0, mDisplayWidth, mDisplayHeight}); |
| backgroundLayer->setZOrder(0); |
| |
| mSideLength = mDisplayWidth < mDisplayHeight ? mDisplayWidth : mDisplayHeight; |
| common::Rect redRect = {0, 0, mSideLength / 2, mSideLength / 2}; |
| common::Rect blueRect = {mSideLength / 2, mSideLength / 2, mSideLength, mSideLength}; |
| |
| mLayer = std::make_shared<TestBufferLayer>(mComposerClient, mGraphicBuffer, |
| *mTestRenderEngine, mPrimaryDisplay, mSideLength, |
| mSideLength, PixelFormat::RGBA_8888); |
| 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 error = |
| mComposerClient->setColorMode(mPrimaryDisplay, mode, RenderIntent::COLORIMETRIC); |
| if (!error.isOk() && |
| (error.getServiceSpecificError() == IComposerClient::EX_UNSUPPORTED || |
| error.getServiceSpecificError() == IComposerClient::EX_BAD_PARAMETER)) { |
| SUCCEED() << "ColorMode not supported, skip test"; |
| return; |
| } |
| |
| if (!getHasReadbackBuffer()) { |
| GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace"; |
| return; |
| } |
| ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mGraphicBuffer, |
| mDisplayWidth, mDisplayHeight, mPixelFormat, mDataspace); |
| ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer()); |
| mLayer->setTransform(Transform::FLIP_H); |
| mLayer->setDataspace(ReadbackHelper::getDataspaceForColorMode(mode), mWriter); |
| |
| std::vector<Color> expectedColors(static_cast<size_t>(mDisplayWidth * mDisplayHeight)); |
| ReadbackHelper::fillColorsArea(expectedColors, mDisplayWidth, |
| {mSideLength / 2, 0, mSideLength, mSideLength / 2}, RED); |
| ReadbackHelper::fillColorsArea(expectedColors, mDisplayWidth, |
| {0, mSideLength / 2, mSideLength / 2, mSideLength}, BLUE); |
| |
| writeLayers(mLayers); |
| ASSERT_TRUE(mReader.takeErrors().empty()); |
| mWriter.validateDisplay(mPrimaryDisplay); |
| execute(); |
| std::vector<int64_t> changedCompositionLayers; |
| std::vector<Composition> changedCompositionTypes; |
| mReader.takeChangedCompositionTypes(mPrimaryDisplay, &changedCompositionLayers, |
| &changedCompositionTypes); |
| if (!changedCompositionLayers.empty()) { |
| GTEST_SUCCEED(); |
| return; |
| } |
| ASSERT_TRUE(mReader.takeErrors().empty()); |
| mWriter.presentDisplay(mPrimaryDisplay); |
| 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) { |
| ASSERT_NO_FATAL_FAILURE( |
| mComposerClient->setColorMode(mPrimaryDisplay, mode, RenderIntent::COLORIMETRIC)); |
| |
| if (!getHasReadbackBuffer()) { |
| GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace"; |
| return; |
| } |
| ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mGraphicBuffer, |
| mDisplayWidth, mDisplayHeight, mPixelFormat, mDataspace); |
| ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer()); |
| |
| mLayer->setTransform(Transform::FLIP_V); |
| mLayer->setDataspace(ReadbackHelper::getDataspaceForColorMode(mode), mWriter); |
| |
| std::vector<Color> expectedColors(static_cast<size_t>(mDisplayWidth * mDisplayHeight)); |
| ReadbackHelper::fillColorsArea(expectedColors, mDisplayWidth, |
| {0, mSideLength / 2, mSideLength / 2, mSideLength}, RED); |
| ReadbackHelper::fillColorsArea(expectedColors, mDisplayWidth, |
| {mSideLength / 2, 0, mSideLength, mSideLength / 2}, BLUE); |
| |
| writeLayers(mLayers); |
| ASSERT_TRUE(mReader.takeErrors().empty()); |
| mWriter.validateDisplay(mPrimaryDisplay); |
| execute(); |
| std::vector<int64_t> changedCompositionLayers; |
| std::vector<Composition> changedCompositionTypes; |
| mReader.takeChangedCompositionTypes(mPrimaryDisplay, &changedCompositionLayers, |
| &changedCompositionTypes); |
| if (!changedCompositionLayers.empty()) { |
| GTEST_SUCCEED(); |
| return; |
| } |
| ASSERT_TRUE(mReader.takeErrors().empty()); |
| mWriter.presentDisplay(mPrimaryDisplay); |
| 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) { |
| ASSERT_NO_FATAL_FAILURE( |
| mComposerClient->setColorMode(mPrimaryDisplay, mode, RenderIntent::COLORIMETRIC)); |
| |
| if (!getHasReadbackBuffer()) { |
| GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace"; |
| return; |
| } |
| ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mGraphicBuffer, |
| mDisplayWidth, mDisplayHeight, mPixelFormat, mDataspace); |
| ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer()); |
| |
| mLayer->setTransform(Transform::ROT_180); |
| mLayer->setDataspace(ReadbackHelper::getDataspaceForColorMode(mode), mWriter); |
| |
| std::vector<Color> expectedColors(static_cast<size_t>(mDisplayWidth * mDisplayHeight)); |
| ReadbackHelper::fillColorsArea(expectedColors, mDisplayWidth, |
| {mSideLength / 2, mSideLength / 2, mSideLength, mSideLength}, |
| RED); |
| ReadbackHelper::fillColorsArea(expectedColors, mDisplayWidth, |
| {0, 0, mSideLength / 2, mSideLength / 2}, BLUE); |
| |
| writeLayers(mLayers); |
| ASSERT_TRUE(mReader.takeErrors().empty()); |
| mWriter.validateDisplay(mPrimaryDisplay); |
| execute(); |
| std::vector<int64_t> layers; |
| std::vector<Composition> types; |
| mReader.takeChangedCompositionTypes(mPrimaryDisplay, &layers, &types); |
| if (!layers.empty()) { |
| GTEST_SUCCEED(); |
| return; |
| } |
| ASSERT_TRUE(mReader.takeErrors().empty()); |
| mWriter.presentDisplay(mPrimaryDisplay); |
| 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)); |
| } |
| } |
| |
| 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); |
| |
| } // namespace |
| } // namespace aidl::android::hardware::graphics::composer3::vts |