Readback tests from VTS 2.2
Tests are from https://source.corp.google.com/android/hardware/interfaces/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2ReadbackTest.cpp;rcl=4796867049599ae1618d63cb93a38b269687164b;l=52
Test: atest VtsHalGraphicsComposer3_TargetTest
BUG: 202766745
Change-Id: I495819c168429873dc88decb20f398569c1a8128
diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/vts/functional/Android.bp b/graphics/composer/aidl/android/hardware/graphics/composer3/vts/functional/Android.bp
index c011f73..9bf8609 100644
--- a/graphics/composer/aidl/android/hardware/graphics/composer3/vts/functional/Android.bp
+++ b/graphics/composer/aidl/android/hardware/graphics/composer3/vts/functional/Android.bp
@@ -19,7 +19,7 @@
// A large-scale-change added 'default_applicable_licenses' to import
// all of the 'license_kinds' from "hardware_interfaces_license"
// to get the below license kinds:
- // SPDX-license-identifier-Apache-2.0
+ // SPDX-license-identifier-Apache-2.0
default_applicable_licenses: ["hardware_interfaces_license"],
}
@@ -28,20 +28,29 @@
defaults: [
"VtsHalTargetTestDefaults",
"use_libaidlvintf_gtest_helper_static",
+ // Needed for librenderengine
+ "skia_deps",
],
srcs: [
"VtsHalGraphicsComposer3_TargetTest.cpp",
+ "VtsHalGraphicsComposer3_ReadbackTest.cpp",
"composer-vts/GraphicsComposerCallback.cpp",
"composer-vts/TestCommandReader.cpp",
],
shared_libs: [
+ "libEGL",
+ "libGLESv1_CM",
+ "libGLESv2",
"libbinder_ndk",
"libbinder",
"libfmq",
"libbase",
"libsync",
"libui",
+ "libgui",
+ "libhidlbase",
+ "libprocessgroup",
"android.hardware.graphics.mapper@2.0",
"android.hardware.graphics.mapper@2.1",
"android.hardware.graphics.mapper@3.0",
@@ -69,6 +78,10 @@
"android.hardware.graphics.mapper@3.0-vts",
"android.hardware.graphics.mapper@4.0-vts",
"libaidlcommonsupport",
+ "libgtest",
+ "librenderengine",
+ "libshaders",
+ "libtonemap",
],
cflags: [
"-Wconversion",
diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/vts/functional/VtsHalGraphicsComposer3_ReadbackTest.cpp b/graphics/composer/aidl/android/hardware/graphics/composer3/vts/functional/VtsHalGraphicsComposer3_ReadbackTest.cpp
new file mode 100644
index 0000000..6f83b90
--- /dev/null
+++ b/graphics/composer/aidl/android/hardware/graphics/composer3/vts/functional/VtsHalGraphicsComposer3_ReadbackTest.cpp
@@ -0,0 +1,1360 @@
+/**
+ * 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"
+#include "composer-vts/include/TestCommandReader.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();
+
+ 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 command writer/reader and gralloc
+ mWriter = std::make_shared<CommandWriterBase>(1024);
+ mReader = std::make_unique<TestCommandReader>();
+ 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));
+ EXPECT_EQ(0, mReader->mErrors.size());
+ EXPECT_EQ(0, mReader->mCompositionChanges.size());
+ 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 clearCommandReaderState() {
+ mReader->mCompositionChanges.clear();
+ mReader->mErrors.clear();
+ }
+
+ void writeLayers(const std::vector<std::shared_ptr<TestLayer>>& layers) {
+ for (auto layer : layers) {
+ layer->write(mWriter);
+ }
+ execute();
+ }
+
+ void execute() {
+ TestCommandReader* reader = mReader.get();
+ CommandWriterBase* writer = mWriter.get();
+ bool queueChanged = false;
+ int32_t commandLength = 0;
+ std::vector<NativeHandle> commandHandles;
+ ASSERT_TRUE(writer->writeQueue(&queueChanged, &commandLength, &commandHandles));
+
+ if (queueChanged) {
+ auto ret = mComposerClient->setInputCommandQueue(writer->getMQDescriptor());
+ ASSERT_TRUE(ret.isOk());
+ }
+
+ ExecuteCommandsStatus commandStatus;
+ EXPECT_TRUE(mComposerClient->executeCommands(commandLength, commandHandles, &commandStatus)
+ .isOk());
+
+ if (commandStatus.queueChanged) {
+ MQDescriptor<int32_t, SynchronizedReadWrite> outputCommandQueue;
+ ASSERT_TRUE(mComposerClient->getOutputCommandQueue(&outputCommandQueue).isOk());
+ reader->setMQDescriptor(outputCommandQueue);
+ }
+ ASSERT_TRUE(reader->readQueue(commandStatus.length, std::move(commandStatus.handles)));
+ reader->parse();
+ reader->reset();
+ writer->reset();
+ }
+
+ 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;
+ int32_t mDisplayWidth;
+ int32_t mDisplayHeight;
+ std::vector<ColorMode> mTestColorModes;
+ std::shared_ptr<CommandWriterBase> mWriter;
+ std::unique_ptr<TestCommandReader> mReader;
+ ::android::sp<::android::GraphicBuffer> mGraphicBuffer;
+ std::unique_ptr<TestRenderEngine> mTestRenderEngine;
+
+ bool mHasReadbackBuffer;
+ 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);
+ }
+ }
+ }
+};
+
+class GraphicsCompositionTest : public GraphicsCompositionTestBase,
+ public testing::WithParamInterface<std::string> {
+ public:
+ void SetUp() override { SetUpBase(GetParam()); }
+};
+
+TEST_P(GraphicsCompositionTest, SingleSolidColorLayer) {
+ for (ColorMode mode : mTestColorModes) {
+ mWriter->selectDisplay(mPrimaryDisplay);
+ ASSERT_NO_FATAL_FAILURE(
+ mComposerClient->setColorMode(mPrimaryDisplay, mode, RenderIntent::COLORIMETRIC));
+
+ ReadbackBufferAttributes readBackBufferAttributes;
+ const auto error = mComposerClient->getReadbackBufferAttributes(mPrimaryDisplay,
+ &readBackBufferAttributes);
+
+ mPixelFormat = readBackBufferAttributes.format;
+ mDataspace = readBackBufferAttributes.dataspace;
+ mHasReadbackBuffer =
+ error.isOk() && ReadbackHelper::readbackSupported(mPixelFormat, mDataspace);
+
+ if (!mHasReadbackBuffer) {
+ 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_EQ(0, mReader->mErrors.size());
+ mWriter->validateDisplay();
+ execute();
+ // if hwc cannot handle and asks for composition change,
+ // just succeed the test
+ if (mReader->mCompositionChanges.size() != 0) {
+ clearCommandReaderState();
+ GTEST_SUCCEED();
+ return;
+ }
+ ASSERT_EQ(0, mReader->mErrors.size());
+ mWriter->presentDisplay();
+ execute();
+ ASSERT_EQ(0, mReader->mErrors.size());
+
+ 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) {
+ mWriter->selectDisplay(mPrimaryDisplay);
+ ASSERT_NO_FATAL_FAILURE(
+ mComposerClient->setColorMode(mPrimaryDisplay, mode, RenderIntent::COLORIMETRIC));
+
+ ReadbackBufferAttributes readBackBufferAttributes;
+ const auto error = mComposerClient->getReadbackBufferAttributes(mPrimaryDisplay,
+ &readBackBufferAttributes);
+
+ mPixelFormat = readBackBufferAttributes.format;
+ mDataspace = readBackBufferAttributes.dataspace;
+ mHasReadbackBuffer =
+ error.isOk() && ReadbackHelper::readbackSupported(mPixelFormat, mDataspace);
+
+ if (!mHasReadbackBuffer) {
+ GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace";
+ return;
+ }
+
+ mWriter->selectDisplay(mPrimaryDisplay);
+
+ 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_EQ(0, mReader->mErrors.size());
+ mWriter->validateDisplay();
+ execute();
+
+ if (mReader->mCompositionChanges.size() != 0) {
+ clearCommandReaderState();
+ GTEST_SUCCEED();
+ return;
+ }
+ ASSERT_EQ(0, mReader->mErrors.size());
+
+ mWriter->presentDisplay();
+ execute();
+
+ ASSERT_EQ(0, mReader->mErrors.size());
+
+ 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) {
+ mWriter->selectDisplay(mPrimaryDisplay);
+ ASSERT_NO_FATAL_FAILURE(
+ mComposerClient->setColorMode(mPrimaryDisplay, mode, RenderIntent::COLORIMETRIC));
+
+ ReadbackBufferAttributes readBackBufferAttributes;
+ const auto error = mComposerClient->getReadbackBufferAttributes(mPrimaryDisplay,
+ &readBackBufferAttributes);
+
+ mPixelFormat = readBackBufferAttributes.format;
+ mDataspace = readBackBufferAttributes.dataspace;
+ mHasReadbackBuffer =
+ error.isOk() && ReadbackHelper::readbackSupported(mPixelFormat, mDataspace);
+
+ if (!mHasReadbackBuffer) {
+ 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(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();
+ execute();
+
+ if (mReader->mCompositionChanges.size() != 0) {
+ clearCommandReaderState();
+ GTEST_SUCCEED();
+ return;
+ }
+ ASSERT_EQ(0, mReader->mErrors.size());
+ mWriter->presentDisplay();
+ execute();
+ ASSERT_EQ(0, mReader->mErrors.size());
+
+ ASSERT_NO_FATAL_FAILURE(readbackBuffer.checkReadbackBuffer(expectedColors));
+ }
+}
+
+TEST_P(GraphicsCompositionTest, ClientComposition) {
+ EXPECT_TRUE(mComposerClient->setClientTargetSlotCount(mPrimaryDisplay, kClientTargetSlotCount)
+ .isOk());
+
+ for (ColorMode mode : mTestColorModes) {
+ mWriter->selectDisplay(mPrimaryDisplay);
+ EXPECT_TRUE(mComposerClient->setColorMode(mPrimaryDisplay, mode, RenderIntent::COLORIMETRIC)
+ .isOk());
+
+ ReadbackBufferAttributes readBackBufferAttributes;
+ const auto error = mComposerClient->getReadbackBufferAttributes(mPrimaryDisplay,
+ &readBackBufferAttributes);
+
+ mPixelFormat = readBackBufferAttributes.format;
+ mDataspace = readBackBufferAttributes.dataspace;
+ mHasReadbackBuffer =
+ error.isOk() && ReadbackHelper::readbackSupported(mPixelFormat, mDataspace);
+
+ if (!mHasReadbackBuffer) {
+ GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace";
+ return;
+ }
+
+ mWriter->selectDisplay(mPrimaryDisplay);
+
+ 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_EQ(0, mReader->mErrors.size());
+ mWriter->validateDisplay();
+ execute();
+
+ if (!mReader->mCompositionChanges.empty()) {
+ ASSERT_EQ(1, mReader->mCompositionChanges.size());
+ ASSERT_EQ(1, mReader->mCompositionChanges[0].second);
+
+ 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();
+ mWriter->setClientTarget(0, mGraphicBuffer->handle, fenceHandle.get(), clientDataspace,
+ std::vector<common::Rect>(1, damage));
+ execute();
+ ASSERT_EQ(0, mReader->mCompositionChanges.size());
+ }
+ ASSERT_EQ(0, mReader->mErrors.size());
+
+ mWriter->presentDisplay();
+ execute();
+
+ ASSERT_EQ(0, mReader->mErrors.size());
+
+ ASSERT_NO_FATAL_FAILURE(readbackBuffer.checkReadbackBuffer(expectedColors));
+ }
+}
+
+TEST_P(GraphicsCompositionTest, DeviceAndClientComposition) {
+ ASSERT_NO_FATAL_FAILURE(
+ mComposerClient->setClientTargetSlotCount(mPrimaryDisplay, kClientTargetSlotCount));
+
+ for (ColorMode mode : mTestColorModes) {
+ mWriter->selectDisplay(mPrimaryDisplay);
+ ASSERT_NO_FATAL_FAILURE(
+ mComposerClient->setColorMode(mPrimaryDisplay, mode, RenderIntent::COLORIMETRIC));
+
+ ReadbackBufferAttributes readBackBufferAttributes;
+ const auto error = mComposerClient->getReadbackBufferAttributes(mPrimaryDisplay,
+ &readBackBufferAttributes);
+
+ mPixelFormat = readBackBufferAttributes.format;
+ mDataspace = readBackBufferAttributes.dataspace;
+ mHasReadbackBuffer =
+ error.isOk() && ReadbackHelper::readbackSupported(mPixelFormat, mDataspace);
+
+ if (!mHasReadbackBuffer) {
+ 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();
+ execute();
+
+ if (mReader->mCompositionChanges.size() != 1) {
+ mReader->mCompositionChanges.clear();
+ continue;
+ }
+ // create client target buffer
+ ASSERT_EQ(1, mReader->mCompositionChanges[0].second);
+ 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();
+ mWriter->setClientTarget(0, mGraphicBuffer->handle, fenceHandle.get(), clientDataspace,
+ std::vector<common::Rect>(1, clientFrame));
+ execute();
+ ASSERT_EQ(0, mReader->mCompositionChanges.size());
+ ASSERT_EQ(0, mReader->mErrors.size());
+
+ mWriter->presentDisplay();
+ execute();
+ ASSERT_EQ(0, mReader->mErrors.size());
+ ASSERT_NO_FATAL_FAILURE(readbackBuffer.checkReadbackBuffer(expectedColors));
+ }
+}
+
+TEST_P(GraphicsCompositionTest, SetLayerDamage) {
+ for (ColorMode mode : mTestColorModes) {
+ mWriter->selectDisplay(mPrimaryDisplay);
+ ASSERT_NO_FATAL_FAILURE(
+ mComposerClient->setColorMode(mPrimaryDisplay, mode, RenderIntent::COLORIMETRIC));
+
+ ReadbackBufferAttributes readBackBufferAttributes;
+ const auto error = mComposerClient->getReadbackBufferAttributes(mPrimaryDisplay,
+ &readBackBufferAttributes);
+
+ mPixelFormat = readBackBufferAttributes.format;
+ mDataspace = readBackBufferAttributes.dataspace;
+ mHasReadbackBuffer =
+ error.isOk() && ReadbackHelper::readbackSupported(mPixelFormat, mDataspace);
+
+ if (!mHasReadbackBuffer) {
+ GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace";
+ return;
+ }
+
+ mWriter->selectDisplay(mPrimaryDisplay);
+
+ 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_EQ(0, mReader->mErrors.size());
+ mWriter->validateDisplay();
+ execute();
+ if (mReader->mCompositionChanges.size() != 0) {
+ clearCommandReaderState();
+ GTEST_SUCCEED();
+ return;
+ }
+ ASSERT_EQ(0, mReader->mErrors.size());
+ mWriter->presentDisplay();
+ execute();
+ ASSERT_EQ(0, mReader->mErrors.size());
+
+ 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_EQ(0, mReader->mErrors.size());
+ mWriter->validateDisplay();
+ execute();
+ ASSERT_EQ(0, mReader->mErrors.size());
+ ASSERT_EQ(0, mReader->mCompositionChanges.size());
+ mWriter->presentDisplay();
+ execute();
+ ASSERT_EQ(0, mReader->mErrors.size());
+
+ ASSERT_NO_FATAL_FAILURE(readbackBuffer.checkReadbackBuffer(expectedColors));
+ }
+}
+
+TEST_P(GraphicsCompositionTest, SetLayerPlaneAlpha) {
+ for (ColorMode mode : mTestColorModes) {
+ mWriter->selectDisplay(mPrimaryDisplay);
+ ASSERT_NO_FATAL_FAILURE(
+ mComposerClient->setColorMode(mPrimaryDisplay, mode, RenderIntent::COLORIMETRIC));
+
+ ReadbackBufferAttributes readBackBufferAttributes;
+ const auto error = mComposerClient->getReadbackBufferAttributes(mPrimaryDisplay,
+ &readBackBufferAttributes);
+
+ mPixelFormat = readBackBufferAttributes.format;
+ mDataspace = readBackBufferAttributes.dataspace;
+ mHasReadbackBuffer =
+ error.isOk() && ReadbackHelper::readbackSupported(mPixelFormat, mDataspace);
+
+ if (!mHasReadbackBuffer) {
+ 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_EQ(0, mReader->mErrors.size());
+ mWriter->validateDisplay();
+ execute();
+ if (mReader->mCompositionChanges.size() != 0) {
+ clearCommandReaderState();
+ GTEST_SUCCEED();
+ return;
+ }
+ ASSERT_EQ(0, mReader->mErrors.size());
+
+ mWriter->presentDisplay();
+ execute();
+ ASSERT_EQ(0, mReader->mErrors.size());
+
+ 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) {
+ mWriter->selectDisplay(mPrimaryDisplay);
+ ASSERT_NO_FATAL_FAILURE(
+ mComposerClient->setColorMode(mPrimaryDisplay, mode, RenderIntent::COLORIMETRIC));
+
+ ReadbackBufferAttributes readBackBufferAttributes;
+ const auto error = mComposerClient->getReadbackBufferAttributes(mPrimaryDisplay,
+ &readBackBufferAttributes);
+
+ mPixelFormat = readBackBufferAttributes.format;
+ mDataspace = readBackBufferAttributes.dataspace;
+ mHasReadbackBuffer =
+ error.isOk() && ReadbackHelper::readbackSupported(mPixelFormat, mDataspace);
+
+ if (!mHasReadbackBuffer) {
+ GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace";
+ return;
+ }
+
+ mWriter->selectDisplay(mPrimaryDisplay);
+
+ 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_EQ(0, mReader->mErrors.size());
+ mWriter->validateDisplay();
+ execute();
+ if (mReader->mCompositionChanges.size() != 0) {
+ clearCommandReaderState();
+ GTEST_SUCCEED();
+ return;
+ }
+ ASSERT_EQ(0, mReader->mErrors.size());
+ mWriter->presentDisplay();
+ execute();
+ ASSERT_EQ(0, mReader->mErrors.size());
+ 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) {
+ mWriter->selectDisplay(mPrimaryDisplay);
+ ASSERT_NO_FATAL_FAILURE(
+ mComposerClient->setColorMode(mPrimaryDisplay, mode, RenderIntent::COLORIMETRIC));
+
+ ReadbackBufferAttributes readBackBufferAttributes;
+ const auto error = mComposerClient->getReadbackBufferAttributes(mPrimaryDisplay,
+ &readBackBufferAttributes);
+
+ mPixelFormat = readBackBufferAttributes.format;
+ mDataspace = readBackBufferAttributes.dataspace;
+ mHasReadbackBuffer =
+ error.isOk() && ReadbackHelper::readbackSupported(mPixelFormat, mDataspace);
+
+ if (!mHasReadbackBuffer) {
+ 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_EQ(0, mReader->mErrors.size());
+ mWriter->validateDisplay();
+ execute();
+ if (mReader->mCompositionChanges.size() != 0) {
+ clearCommandReaderState();
+ GTEST_SUCCEED();
+ return;
+ }
+ mWriter->presentDisplay();
+ execute();
+ ASSERT_EQ(0, mReader->mErrors.size());
+
+ 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_EQ(0, mReader->mErrors.size());
+ mWriter->validateDisplay();
+ execute();
+ ASSERT_EQ(0, mReader->mCompositionChanges.size());
+ ASSERT_EQ(0, mReader->mErrors.size());
+ mWriter->presentDisplay();
+ execute();
+ ASSERT_EQ(0, mReader->mErrors.size());
+
+ 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) {
+ mWriter->selectDisplay(mPrimaryDisplay);
+ ASSERT_NO_FATAL_FAILURE(
+ mComposerClient->setColorMode(mPrimaryDisplay, mode, RenderIntent::COLORIMETRIC));
+
+ ReadbackBufferAttributes readBackBufferAttributes;
+ const auto error = mComposerClient->getReadbackBufferAttributes(mPrimaryDisplay,
+ &readBackBufferAttributes);
+
+ mPixelFormat = readBackBufferAttributes.format;
+ mDataspace = readBackBufferAttributes.dataspace;
+ mHasReadbackBuffer =
+ error.isOk() && ReadbackHelper::readbackSupported(mPixelFormat, mDataspace);
+
+ if (!mHasReadbackBuffer) {
+ GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace";
+ return;
+ }
+
+ mWriter->selectDisplay(mPrimaryDisplay);
+
+ 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_EQ(0, mReader->mErrors.size());
+ mWriter->validateDisplay();
+ execute();
+ if (mReader->mCompositionChanges.size() != 0) {
+ clearCommandReaderState();
+ GTEST_SUCCEED();
+ return;
+ }
+ ASSERT_EQ(0, mReader->mErrors.size());
+ mWriter->presentDisplay();
+ execute();
+ ASSERT_EQ(0, mReader->mErrors.size());
+
+ 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) {
+ mWriter->selectDisplay(mPrimaryDisplay);
+ ASSERT_NO_FATAL_FAILURE(
+ mComposerClient->setColorMode(mPrimaryDisplay, mode, RenderIntent::COLORIMETRIC));
+
+ ReadbackBufferAttributes readBackBufferAttributes;
+ const auto error = mComposerClient->getReadbackBufferAttributes(mPrimaryDisplay,
+ &readBackBufferAttributes);
+
+ mPixelFormat = readBackBufferAttributes.format;
+ mDataspace = readBackBufferAttributes.dataspace;
+ mHasReadbackBuffer =
+ error.isOk() && ReadbackHelper::readbackSupported(mPixelFormat, mDataspace);
+
+ if (!mHasReadbackBuffer) {
+ GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace";
+ return;
+ }
+
+ mWriter->selectDisplay(mPrimaryDisplay);
+
+ 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_EQ(0, mReader->mErrors.size());
+ mWriter->validateDisplay();
+ execute();
+ if (mReader->mCompositionChanges.size() != 0) {
+ clearCommandReaderState();
+ GTEST_SUCCEED();
+ return;
+ }
+ ASSERT_EQ(0, mReader->mErrors.size());
+ mWriter->presentDisplay();
+ execute();
+ ASSERT_EQ(0, mReader->mErrors.size());
+ ASSERT_NO_FATAL_FAILURE(readbackBuffer.checkReadbackBuffer(expectedColors));
+ }
+}
+
+TEST_P(GraphicsBlendModeCompositionTest, Premultiplied) {
+ for (ColorMode mode : mTestColorModes) {
+ mWriter->selectDisplay(mPrimaryDisplay);
+ ASSERT_NO_FATAL_FAILURE(
+ mComposerClient->setColorMode(mPrimaryDisplay, mode, RenderIntent::COLORIMETRIC));
+
+ ReadbackBufferAttributes readBackBufferAttributes;
+ const auto error = mComposerClient->getReadbackBufferAttributes(mPrimaryDisplay,
+ &readBackBufferAttributes);
+
+ mPixelFormat = readBackBufferAttributes.format;
+ mDataspace = readBackBufferAttributes.dataspace;
+ mHasReadbackBuffer =
+ error.isOk() && ReadbackHelper::readbackSupported(mPixelFormat, mDataspace);
+
+ if (!mHasReadbackBuffer) {
+ GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace";
+ return;
+ }
+ mWriter->selectDisplay(mPrimaryDisplay);
+
+ 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_EQ(0, mReader->mErrors.size());
+ mWriter->validateDisplay();
+ execute();
+ if (mReader->mCompositionChanges.size() != 0) {
+ clearCommandReaderState();
+ GTEST_SUCCEED();
+ return;
+ }
+ ASSERT_EQ(0, mReader->mErrors.size());
+ mWriter->presentDisplay();
+ execute();
+ ASSERT_EQ(0, mReader->mErrors.size());
+ 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();
+ mWriter->selectDisplay(mPrimaryDisplay);
+ 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) {
+ ASSERT_NE(nullptr, mWriter);
+ mWriter->selectDisplay(mPrimaryDisplay);
+ 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;
+ }
+
+ ReadbackBufferAttributes readBackBufferAttributes;
+ error = mComposerClient->getReadbackBufferAttributes(mPrimaryDisplay,
+ &readBackBufferAttributes);
+
+ mPixelFormat = readBackBufferAttributes.format;
+ mDataspace = readBackBufferAttributes.dataspace;
+ mHasReadbackBuffer =
+ error.isOk() && ReadbackHelper::readbackSupported(mPixelFormat, mDataspace);
+
+ if (!mHasReadbackBuffer) {
+ 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_EQ(0, mReader->mErrors.size());
+ mWriter->validateDisplay();
+ execute();
+ if (mReader->mCompositionChanges.size() != 0) {
+ clearCommandReaderState();
+ GTEST_SUCCEED();
+ return;
+ }
+ ASSERT_EQ(0, mReader->mErrors.size());
+ mWriter->presentDisplay();
+ execute();
+ ASSERT_EQ(0, mReader->mErrors.size());
+
+ 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) {
+ mWriter->selectDisplay(mPrimaryDisplay);
+ ASSERT_NO_FATAL_FAILURE(
+ mComposerClient->setColorMode(mPrimaryDisplay, mode, RenderIntent::COLORIMETRIC));
+
+ ReadbackBufferAttributes readBackBufferAttributes;
+ const auto error = mComposerClient->getReadbackBufferAttributes(mPrimaryDisplay,
+ &readBackBufferAttributes);
+
+ mPixelFormat = readBackBufferAttributes.format;
+ mDataspace = readBackBufferAttributes.dataspace;
+ mHasReadbackBuffer =
+ error.isOk() && ReadbackHelper::readbackSupported(mPixelFormat, mDataspace);
+
+ if (!mHasReadbackBuffer) {
+ 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_EQ(0, mReader->mErrors.size());
+ mWriter->validateDisplay();
+ execute();
+ if (mReader->mCompositionChanges.size() != 0) {
+ clearCommandReaderState();
+ GTEST_SUCCEED();
+ return;
+ }
+ ASSERT_EQ(0, mReader->mErrors.size());
+ mWriter->presentDisplay();
+ execute();
+ ASSERT_EQ(0, mReader->mErrors.size());
+ 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) {
+ mWriter->selectDisplay(mPrimaryDisplay);
+ ASSERT_NO_FATAL_FAILURE(
+ mComposerClient->setColorMode(mPrimaryDisplay, mode, RenderIntent::COLORIMETRIC));
+
+ ReadbackBufferAttributes readBackBufferAttributes;
+ const auto error = mComposerClient->getReadbackBufferAttributes(mPrimaryDisplay,
+ &readBackBufferAttributes);
+
+ mPixelFormat = readBackBufferAttributes.format;
+ mDataspace = readBackBufferAttributes.dataspace;
+ mHasReadbackBuffer =
+ error.isOk() && ReadbackHelper::readbackSupported(mPixelFormat, mDataspace);
+ if (!mHasReadbackBuffer) {
+ 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_EQ(0, mReader->mErrors.size());
+ mWriter->validateDisplay();
+ execute();
+ if (!mReader->mCompositionChanges.empty()) {
+ clearCommandReaderState();
+ GTEST_SUCCEED();
+ return;
+ }
+ ASSERT_EQ(0, mReader->mErrors.size());
+ mWriter->presentDisplay();
+ execute();
+ ASSERT_EQ(0, mReader->mErrors.size());
+ 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
\ No newline at end of file
diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/vts/functional/composer-vts/Android.bp b/graphics/composer/aidl/android/hardware/graphics/composer3/vts/functional/composer-vts/Android.bp
index 00ea4f3..2b058c7 100644
--- a/graphics/composer/aidl/android/hardware/graphics/composer3/vts/functional/composer-vts/Android.bp
+++ b/graphics/composer/aidl/android/hardware/graphics/composer3/vts/functional/composer-vts/Android.bp
@@ -29,6 +29,8 @@
srcs: [
"GraphicsComposerCallback.cpp",
"TestCommandReader.cpp",
+ "ReadbackVts.cpp",
+ "RenderEngineVts.cpp",
],
header_libs: [
"android.hardware.graphics.composer3-command-buffer",
@@ -38,20 +40,32 @@
"android.hardware.graphics.common-V3-ndk",
"android.hardware.common-V2-ndk",
"android.hardware.common.fmq-V1-ndk",
+ "libarect",
"libgtest",
"libbase",
"libfmq",
"libsync",
+ "libmath",
"libaidlcommonsupport",
+ "libnativewindow",
+ "librenderengine",
+ "libshaders",
+ "libtonemap",
"android.hardware.graphics.mapper@2.0-vts",
+ "android.hardware.graphics.mapper@2.1-vts",
"android.hardware.graphics.mapper@3.0-vts",
"android.hardware.graphics.mapper@4.0-vts",
],
shared_libs: [
"libbinder_ndk",
"libhidlbase",
+ "libui",
"android.hardware.graphics.composer3-V1-ndk",
],
+ export_static_lib_headers: [
+ "android.hardware.graphics.mapper@2.1-vts",
+ "librenderengine",
+ ],
cflags: [
"-O0",
"-g",
diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/vts/functional/composer-vts/ReadbackVts.cpp b/graphics/composer/aidl/android/hardware/graphics/composer3/vts/functional/composer-vts/ReadbackVts.cpp
new file mode 100644
index 0000000..e832cb7
--- /dev/null
+++ b/graphics/composer/aidl/android/hardware/graphics/composer3/vts/functional/composer-vts/ReadbackVts.cpp
@@ -0,0 +1,360 @@
+/**
+ * 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.
+ */
+
+// TODO(b/129481165): remove the #pragma below and fix conversion issues
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wconversion"
+
+#include "include/ReadbackVts.h"
+#include <aidl/android/hardware/graphics/common/BufferUsage.h>
+#include "include/RenderEngineVts.h"
+#include "renderengine/ExternalTexture.h"
+
+// TODO(b/129481165): remove the #pragma below and fix conversion issues
+#pragma clang diagnostic pop // ignored "-Wconversion
+
+namespace aidl::android::hardware::graphics::composer3::vts {
+
+const std::vector<ColorMode> ReadbackHelper::colorModes = {ColorMode::SRGB, ColorMode::DISPLAY_P3};
+const std::vector<Dataspace> ReadbackHelper::dataspaces = {common::Dataspace::SRGB,
+ common::Dataspace::DISPLAY_P3};
+
+void TestLayer::write(const std::shared_ptr<CommandWriterBase>& writer) {
+ writer->selectLayer(mLayer);
+ writer->setLayerDisplayFrame(mDisplayFrame);
+ writer->setLayerSourceCrop(mSourceCrop);
+ writer->setLayerZOrder(mZOrder);
+ writer->setLayerSurfaceDamage(mSurfaceDamage);
+ writer->setLayerTransform(mTransform);
+ writer->setLayerPlaneAlpha(mAlpha);
+ writer->setLayerBlendMode(mBlendMode);
+}
+
+std::string ReadbackHelper::getColorModeString(ColorMode mode) {
+ switch (mode) {
+ case ColorMode::SRGB:
+ return {"SRGB"};
+ case ColorMode::DISPLAY_P3:
+ return {"DISPLAY_P3"};
+ default:
+ return {"Unsupported color mode for readback"};
+ }
+}
+
+std::string ReadbackHelper::getDataspaceString(common::Dataspace dataspace) {
+ switch (dataspace) {
+ case common::Dataspace::SRGB:
+ return {"SRGB"};
+ case common::Dataspace::DISPLAY_P3:
+ return {"DISPLAY_P3"};
+ case common::Dataspace::UNKNOWN:
+ return {"UNKNOWN"};
+ default:
+ return {"Unsupported dataspace for readback"};
+ }
+}
+
+Dataspace ReadbackHelper::getDataspaceForColorMode(ColorMode mode) {
+ switch (mode) {
+ case ColorMode::DISPLAY_P3:
+ return Dataspace::DISPLAY_P3;
+ case ColorMode::SRGB:
+ default:
+ return common::Dataspace::UNKNOWN;
+ }
+}
+
+LayerSettings TestLayer::toRenderEngineLayerSettings() {
+ LayerSettings layerSettings;
+
+ layerSettings.alpha = ::android::half(mAlpha);
+ layerSettings.disableBlending = mBlendMode == BlendMode::NONE;
+ layerSettings.geometry.boundaries = ::android::FloatRect(
+ static_cast<float>(mDisplayFrame.left), static_cast<float>(mDisplayFrame.top),
+ static_cast<float>(mDisplayFrame.right), static_cast<float>(mDisplayFrame.bottom));
+
+ const ::android::mat4 translation = ::android::mat4::translate(::android::vec4(
+ (static_cast<uint64_t>(mTransform) & static_cast<uint64_t>(Transform::FLIP_H)
+ ? static_cast<float>(-mDisplayFrame.right)
+ : 0.0f),
+ (static_cast<uint64_t>(mTransform) & static_cast<uint64_t>(Transform::FLIP_V)
+ ? static_cast<float>(-mDisplayFrame.bottom)
+ : 0.0f),
+ 0.0f, 1.0f));
+
+ const ::android::mat4 scale = ::android::mat4::scale(::android::vec4(
+ static_cast<uint64_t>(mTransform) & static_cast<uint64_t>(Transform::FLIP_H) ? -1.0f
+ : 1.0f,
+ static_cast<uint64_t>(mTransform) & static_cast<uint64_t>(Transform::FLIP_V) ? -1.0f
+ : 1.0f,
+ 1.0f, 1.0f));
+
+ layerSettings.geometry.positionTransform = scale * translation;
+
+ return layerSettings;
+}
+
+int32_t ReadbackHelper::GetBytesPerPixel(common::PixelFormat pixelFormat) {
+ switch (pixelFormat) {
+ case common::PixelFormat::RGBA_8888:
+ return 4;
+ case common::PixelFormat::RGB_888:
+ return 3;
+ default:
+ return -1;
+ }
+}
+
+void ReadbackHelper::fillBuffer(uint32_t width, uint32_t height, uint32_t stride, void* bufferData,
+ common::PixelFormat pixelFormat,
+ std::vector<Color> desiredPixelColors) {
+ ASSERT_TRUE(pixelFormat == common::PixelFormat::RGB_888 ||
+ pixelFormat == common::PixelFormat::RGBA_8888);
+ int32_t bytesPerPixel = GetBytesPerPixel(pixelFormat);
+ ASSERT_NE(-1, bytesPerPixel);
+ for (int row = 0; row < height; row++) {
+ for (int col = 0; col < width; col++) {
+ auto pixel = row * static_cast<int32_t>(width) + col;
+ Color srcColor = desiredPixelColors[static_cast<size_t>(pixel)];
+
+ int offset = (row * static_cast<int32_t>(stride) + col) * bytesPerPixel;
+ uint8_t* pixelColor = (uint8_t*)bufferData + offset;
+ pixelColor[0] = static_cast<uint8_t>(srcColor.r);
+ pixelColor[1] = static_cast<uint8_t>(srcColor.g);
+ pixelColor[2] = static_cast<uint8_t>(srcColor.b);
+
+ if (bytesPerPixel == 4) {
+ pixelColor[3] = static_cast<uint8_t>(srcColor.a);
+ }
+ }
+ }
+}
+
+void ReadbackHelper::clearColors(std::vector<Color>& expectedColors, int32_t width, int32_t height,
+ int32_t displayWidth) {
+ for (int row = 0; row < height; row++) {
+ for (int col = 0; col < width; col++) {
+ int pixel = row * displayWidth + col;
+ expectedColors[static_cast<size_t>(pixel)] = BLACK;
+ }
+ }
+}
+
+void ReadbackHelper::fillColorsArea(std::vector<Color>& expectedColors, int32_t stride, Rect area,
+ Color color) {
+ for (int row = area.top; row < area.bottom; row++) {
+ for (int col = area.left; col < area.right; col++) {
+ int pixel = row * stride + col;
+ expectedColors[static_cast<size_t>(pixel)] = color;
+ }
+ }
+}
+
+bool ReadbackHelper::readbackSupported(const common::PixelFormat& pixelFormat,
+ const common::Dataspace& dataspace) {
+ if (pixelFormat != common::PixelFormat::RGB_888 &&
+ pixelFormat != common::PixelFormat::RGBA_8888) {
+ return false;
+ }
+ if (std::find(dataspaces.begin(), dataspaces.end(), dataspace) == dataspaces.end()) {
+ return false;
+ }
+ return true;
+}
+
+void ReadbackHelper::compareColorBuffers(std::vector<Color>& expectedColors, void* bufferData,
+ const int32_t stride, const uint32_t width,
+ const uint32_t height, common::PixelFormat pixelFormat) {
+ const int32_t bytesPerPixel = ReadbackHelper::GetBytesPerPixel(pixelFormat);
+ ASSERT_NE(-1, bytesPerPixel);
+ for (int row = 0; row < height; row++) {
+ for (int col = 0; col < width; col++) {
+ auto pixel = row * static_cast<int32_t>(width) + col;
+ int offset = (row * stride + col) * bytesPerPixel;
+ uint8_t* pixelColor = (uint8_t*)bufferData + offset;
+
+ ASSERT_EQ(static_cast<int8_t>(expectedColors[static_cast<size_t>(pixel)].r),
+ pixelColor[0]);
+ ASSERT_EQ(static_cast<int8_t>(expectedColors[static_cast<size_t>(pixel)].g),
+ pixelColor[1]);
+ ASSERT_EQ(static_cast<int8_t>(expectedColors[static_cast<size_t>(pixel)].b),
+ pixelColor[2]);
+ }
+ }
+}
+
+ReadbackBuffer::ReadbackBuffer(int64_t display, const std::shared_ptr<IComposerClient>& client,
+ const ::android::sp<::android::GraphicBuffer>& graphicBuffer,
+ int32_t width, int32_t height, common::PixelFormat pixelFormat,
+ common::Dataspace dataspace) {
+ mDisplay = display;
+
+ mComposerClient = client;
+ mGraphicBuffer = graphicBuffer;
+
+ mPixelFormat = pixelFormat;
+ mDataspace = dataspace;
+
+ mWidth = static_cast<uint32_t>(width);
+ mHeight = static_cast<uint32_t>(height);
+ mLayerCount = 1;
+ mUsage = static_cast<uint64_t>(static_cast<uint64_t>(common::BufferUsage::CPU_READ_OFTEN) |
+ static_cast<uint64_t>(common::BufferUsage::GPU_TEXTURE));
+
+ mAccessRegion.top = 0;
+ mAccessRegion.left = 0;
+ mAccessRegion.right = static_cast<int32_t>(width);
+ mAccessRegion.bottom = static_cast<int32_t>(height);
+}
+
+::android::sp<::android::GraphicBuffer> ReadbackBuffer::allocate() {
+ return ::android::sp<::android::GraphicBuffer>::make(
+ mWidth, mHeight, static_cast<::android::PixelFormat>(mPixelFormat), mLayerCount, mUsage,
+ "ReadbackVts");
+}
+
+void ReadbackBuffer::setReadbackBuffer() {
+ mGraphicBuffer = allocate();
+ 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);
+ EXPECT_TRUE(mComposerClient->setReadbackBuffer(mDisplay, bufferHandle, fence).isOk());
+}
+
+void ReadbackBuffer::checkReadbackBuffer(std::vector<Color> expectedColors) {
+ // lock buffer for reading
+ ndk::ScopedFileDescriptor fenceHandle;
+ EXPECT_TRUE(mComposerClient->getReadbackBufferFence(mDisplay, &fenceHandle).isOk());
+
+ int outBytesPerPixel;
+ int outBytesPerStride;
+ auto status = mGraphicBuffer->lockAsync(mUsage, mAccessRegion, nullptr, fenceHandle.get(),
+ &outBytesPerPixel, &outBytesPerStride);
+ EXPECT_EQ(::android::OK, status);
+ ASSERT_TRUE(mPixelFormat == PixelFormat::RGB_888 || mPixelFormat == PixelFormat::RGBA_8888);
+ ReadbackHelper::compareColorBuffers(expectedColors, mGraphicBuffer.get(),
+ static_cast<int32_t>(mStride), mWidth, mHeight,
+ mPixelFormat);
+ status = mGraphicBuffer->unlock();
+ EXPECT_EQ(::android::OK, status);
+}
+
+void TestColorLayer::write(const std::shared_ptr<CommandWriterBase>& writer) {
+ TestLayer::write(writer);
+ writer->setLayerCompositionType(Composition::SOLID_COLOR);
+ writer->setLayerColor(mColor);
+}
+
+LayerSettings TestColorLayer::toRenderEngineLayerSettings() {
+ LayerSettings layerSettings = TestLayer::toRenderEngineLayerSettings();
+
+ layerSettings.source.solidColor =
+ ::android::half3(static_cast<::android::half>(mColor.r) / 255.0,
+ static_cast<::android::half>(mColor.g) / 255.0,
+ static_cast<::android::half>(mColor.b) / 255.0);
+ layerSettings.alpha =
+ mAlpha * static_cast<float>((static_cast<::android::half>(mColor.a) / 255.0));
+ return layerSettings;
+}
+
+TestBufferLayer::TestBufferLayer(const std::shared_ptr<IComposerClient>& client,
+ const ::android::sp<::android::GraphicBuffer>& graphicBuffer,
+ TestRenderEngine& renderEngine, int32_t display, uint32_t width,
+ uint32_t height, common::PixelFormat format,
+ Composition composition)
+ : TestLayer{client, display}, mRenderEngine(renderEngine) {
+ mGraphicBuffer = graphicBuffer;
+ mComposition = composition;
+ mWidth = width;
+ mHeight = height;
+ mLayerCount = 1;
+ mPixelFormat = format;
+ mUsage = (static_cast<uint64_t>(common::BufferUsage::CPU_READ_OFTEN) |
+ static_cast<uint64_t>(common::BufferUsage::CPU_WRITE_OFTEN) |
+ static_cast<uint64_t>(common::BufferUsage::COMPOSER_OVERLAY) |
+ static_cast<uint64_t>(common::BufferUsage::GPU_TEXTURE));
+
+ mAccessRegion.top = 0;
+ mAccessRegion.left = 0;
+ mAccessRegion.right = static_cast<int32_t>(width);
+ mAccessRegion.bottom = static_cast<int32_t>(height);
+
+ setSourceCrop({0, 0, (float)width, (float)height});
+}
+
+void TestBufferLayer::write(const std::shared_ptr<CommandWriterBase>& writer) {
+ TestLayer::write(writer);
+ writer->setLayerCompositionType(mComposition);
+ writer->setLayerVisibleRegion(std::vector<Rect>(1, mDisplayFrame));
+ if (mGraphicBuffer->handle != nullptr)
+ writer->setLayerBuffer(0, mGraphicBuffer->handle, mFillFence);
+}
+
+LayerSettings TestBufferLayer::toRenderEngineLayerSettings() {
+ LayerSettings layerSettings = TestLayer::toRenderEngineLayerSettings();
+ layerSettings.source.buffer.buffer = std::make_shared<::android::renderengine::ExternalTexture>(
+ ::android::sp<::android::GraphicBuffer>::make(
+ mGraphicBuffer->handle, ::android::GraphicBuffer::CLONE_HANDLE, mWidth, mHeight,
+ static_cast<int32_t>(mPixelFormat), 1, mUsage, mStride),
+ mRenderEngine.getInternalRenderEngine(),
+ ::android::renderengine::ExternalTexture::Usage::READABLE);
+
+ layerSettings.source.buffer.usePremultipliedAlpha = mBlendMode == BlendMode::PREMULTIPLIED;
+
+ const float scaleX = (mSourceCrop.right - mSourceCrop.left) / (static_cast<float>(mWidth));
+ const float scaleY = (mSourceCrop.bottom - mSourceCrop.top) / (static_cast<float>(mHeight));
+ const float translateX = mSourceCrop.left / (static_cast<float>(mWidth));
+ const float translateY = mSourceCrop.top / (static_cast<float>(mHeight));
+
+ layerSettings.source.buffer.textureTransform =
+ ::android::mat4::translate(::android::vec4(translateX, translateY, 0, 1)) *
+ ::android::mat4::scale(::android::vec4(scaleX, scaleY, 1.0, 1.0));
+
+ return layerSettings;
+}
+
+void TestBufferLayer::fillBuffer(std::vector<Color>& expectedColors) {
+ void* bufData;
+ auto status = mGraphicBuffer->lock(mUsage, &bufData);
+ EXPECT_EQ(::android::OK, status);
+ ASSERT_NO_FATAL_FAILURE(ReadbackHelper::fillBuffer(mWidth, mHeight, mStride, bufData,
+ mPixelFormat, expectedColors));
+ EXPECT_EQ(::android::OK, mGraphicBuffer->unlock());
+}
+
+void TestBufferLayer::setBuffer(std::vector<Color> colors) {
+ mGraphicBuffer->reallocate(mWidth, mHeight, static_cast<::android::PixelFormat>(mPixelFormat),
+ mLayerCount, mUsage);
+ ASSERT_NE(nullptr, mGraphicBuffer);
+ ASSERT_NE(nullptr, mGraphicBuffer->handle);
+ ASSERT_NO_FATAL_FAILURE(fillBuffer(colors));
+ ASSERT_EQ(::android::OK, mGraphicBuffer->initCheck());
+}
+
+void TestBufferLayer::setDataspace(common::Dataspace dataspace,
+ const std::shared_ptr<CommandWriterBase>& writer) {
+ writer->selectLayer(mLayer);
+ writer->setLayerDataspace(dataspace);
+}
+
+void TestBufferLayer::setToClientComposition(const std::shared_ptr<CommandWriterBase>& writer) {
+ writer->selectLayer(mLayer);
+ writer->setLayerCompositionType(Composition::CLIENT);
+}
+
+} // namespace aidl::android::hardware::graphics::composer3::vts
\ No newline at end of file
diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/vts/functional/composer-vts/RenderEngineVts.cpp b/graphics/composer/aidl/android/hardware/graphics/composer3/vts/functional/composer-vts/RenderEngineVts.cpp
new file mode 100644
index 0000000..e83750e
--- /dev/null
+++ b/graphics/composer/aidl/android/hardware/graphics/composer3/vts/functional/composer-vts/RenderEngineVts.cpp
@@ -0,0 +1,89 @@
+/**
+ * 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.
+ */
+
+#include "include/RenderEngineVts.h"
+
+namespace aidl::android::hardware::graphics::composer3::vts {
+
+using ::android::hardware::graphics::mapper::V2_1::IMapper;
+using ::android::renderengine::DisplaySettings;
+using ::android::renderengine::LayerSettings;
+using ::android::renderengine::RenderEngineCreationArgs;
+
+TestRenderEngine::TestRenderEngine(const RenderEngineCreationArgs& args) {
+ mFormat = static_cast<common::PixelFormat>(args.pixelFormat);
+ mRenderEngine = ::android::renderengine::RenderEngine::create(args);
+}
+
+TestRenderEngine::~TestRenderEngine() {
+ mRenderEngine.release();
+}
+
+void TestRenderEngine::setRenderLayers(std::vector<std::shared_ptr<TestLayer>> layers) {
+ sort(layers.begin(), layers.end(),
+ [](const std::shared_ptr<TestLayer>& lhs, const std::shared_ptr<TestLayer>& rhs) -> bool {
+ return lhs->getZOrder() < rhs->getZOrder();
+ });
+
+ if (!mCompositionLayers.empty()) {
+ mCompositionLayers.clear();
+ }
+ for (auto& layer : layers) {
+ LayerSettings settings = layer->toRenderEngineLayerSettings();
+ mCompositionLayers.push_back(settings);
+ }
+}
+
+void TestRenderEngine::initGraphicBuffer(uint32_t width, uint32_t height, uint32_t layerCount,
+ uint64_t usage) {
+ mGraphicBuffer = ::android::sp<::android::GraphicBuffer>::make(
+ width, height, static_cast<int32_t>(mFormat), layerCount, usage);
+}
+
+void TestRenderEngine::drawLayers() {
+ ::android::base::unique_fd bufferFence;
+
+ std::vector<::android::renderengine::LayerSettings> compositionLayers;
+ compositionLayers.reserve(mCompositionLayers.size());
+ std::transform(mCompositionLayers.begin(), mCompositionLayers.end(),
+ std::back_insert_iterator(compositionLayers),
+ [](::android::renderengine::LayerSettings& settings)
+ -> ::android::renderengine::LayerSettings { return settings; });
+ auto texture = std::make_shared<::android::renderengine::ExternalTexture>(
+ mGraphicBuffer, *mRenderEngine,
+ ::android::renderengine::ExternalTexture::Usage::WRITEABLE);
+ auto [status, readyFence] = mRenderEngine
+ ->drawLayers(mDisplaySettings, compositionLayers, texture,
+ true, std::move(bufferFence))
+ .get();
+ int fd = readyFence.release();
+ if (fd != -1) {
+ ASSERT_EQ(0, sync_wait(fd, -1));
+ ASSERT_EQ(0, close(fd));
+ }
+}
+
+void TestRenderEngine::checkColorBuffer(std::vector<Color>& expectedColors) {
+ void* bufferData;
+ ASSERT_EQ(0,
+ mGraphicBuffer->lock(static_cast<uint32_t>(mGraphicBuffer->getUsage()), &bufferData));
+ ReadbackHelper::compareColorBuffers(
+ expectedColors, bufferData, static_cast<int32_t>(mGraphicBuffer->getStride()),
+ mGraphicBuffer->getWidth(), mGraphicBuffer->getHeight(), mFormat);
+ ASSERT_EQ(::android::OK, mGraphicBuffer->unlock());
+}
+
+} // namespace aidl::android::hardware::graphics::composer3::vts
\ No newline at end of file
diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/vts/functional/composer-vts/include/ReadbackVts.h b/graphics/composer/aidl/android/hardware/graphics/composer3/vts/functional/composer-vts/include/ReadbackVts.h
new file mode 100644
index 0000000..58989d8
--- /dev/null
+++ b/graphics/composer/aidl/android/hardware/graphics/composer3/vts/functional/composer-vts/include/ReadbackVts.h
@@ -0,0 +1,214 @@
+/**
+ * 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.
+ */
+
+#pragma once
+
+// TODO(b/129481165): remove the #pragma below and fix conversion issues
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wconversion"
+
+#include <GraphicsComposerCallback.h>
+#include <TestCommandReader.h>
+#include <aidl/android/hardware/graphics/composer3/IComposerClient.h>
+#include <android-base/unique_fd.h>
+#include <android/hardware/graphics/composer3/command-buffer.h>
+#include <mapper-vts/2.1/MapperVts.h>
+#include <renderengine/RenderEngine.h>
+#include <ui/GraphicBuffer.h>
+
+#include <memory>
+
+// TODO(b/129481165): remove the #pragma below and fix conversion issues
+#pragma clang diagnostic pop // ignored "-Wconversion
+
+namespace aidl::android::hardware::graphics::composer3::vts {
+
+using ::android::renderengine::LayerSettings;
+using common::Dataspace;
+using common::PixelFormat;
+using IMapper2_1 = ::android::hardware::graphics::mapper::V2_1::IMapper;
+
+static const Color BLACK = {0, 0, 0, static_cast<int8_t>(0xff)};
+static const Color RED = {static_cast<int8_t>(0xff), 0, 0, static_cast<int8_t>(0xff)};
+static const Color TRANSLUCENT_RED = {static_cast<int8_t>(0xff), 0, 0, 0x33};
+static const Color GREEN = {0, static_cast<int8_t>(0xff), 0, static_cast<int8_t>(0xff)};
+static const Color BLUE = {0, 0, static_cast<int8_t>(0xff), static_cast<int8_t>(0xff)};
+static const Color WHITE = {static_cast<int8_t>(0xff), static_cast<int8_t>(0xff),
+ static_cast<int8_t>(0xff), static_cast<int8_t>(0xff)};
+
+class TestRenderEngine;
+
+class TestLayer {
+ public:
+ TestLayer(const std::shared_ptr<IComposerClient>& client, int32_t display)
+ : mComposerClient(client) {
+ client->createLayer(display, kBufferSlotCount, &mLayer);
+ }
+
+ // ComposerClient will take care of destroying layers, no need to explicitly
+ // call destroyLayers here
+ virtual ~TestLayer(){};
+
+ virtual void write(const std::shared_ptr<CommandWriterBase>& writer);
+ virtual LayerSettings toRenderEngineLayerSettings();
+
+ void setDisplayFrame(Rect frame) { mDisplayFrame = frame; }
+ void setSourceCrop(FRect crop) { mSourceCrop = crop; }
+ void setZOrder(uint32_t z) { mZOrder = z; }
+
+ void setSurfaceDamage(std::vector<Rect> surfaceDamage) {
+ mSurfaceDamage = std::move(surfaceDamage);
+ }
+
+ void setTransform(Transform transform) { mTransform = transform; }
+ void setAlpha(float alpha) { mAlpha = alpha; }
+ void setBlendMode(BlendMode blendMode) { mBlendMode = blendMode; }
+
+ BlendMode getBlendMode() const { return mBlendMode; }
+
+ uint32_t getZOrder() const { return mZOrder; }
+
+ float getAlpha() const { return mAlpha; }
+
+ protected:
+ int64_t mLayer;
+ Rect mDisplayFrame = {0, 0, 0, 0};
+ std::vector<Rect> mSurfaceDamage;
+ Transform mTransform = static_cast<Transform>(0);
+ FRect mSourceCrop = {0, 0, 0, 0};
+ static constexpr uint32_t kBufferSlotCount = 64;
+ float mAlpha = 1.0;
+ BlendMode mBlendMode = BlendMode::NONE;
+ uint32_t mZOrder = 0;
+
+ private:
+ std::shared_ptr<IComposerClient> const mComposerClient;
+};
+
+class TestColorLayer : public TestLayer {
+ public:
+ TestColorLayer(const std::shared_ptr<IComposerClient>& client, int32_t display)
+ : TestLayer{client, display} {}
+
+ void write(const std::shared_ptr<CommandWriterBase>& writer) override;
+
+ LayerSettings toRenderEngineLayerSettings() override;
+
+ void setColor(Color color) { mColor = color; }
+
+ private:
+ Color mColor = WHITE;
+};
+
+class TestBufferLayer : public TestLayer {
+ public:
+ TestBufferLayer(const std::shared_ptr<IComposerClient>& client,
+ const ::android::sp<::android::GraphicBuffer>& graphicBuffer,
+ TestRenderEngine& renderEngine, int32_t display, uint32_t width,
+ uint32_t height, common::PixelFormat format,
+ Composition composition = Composition::DEVICE);
+
+ void write(const std::shared_ptr<CommandWriterBase>& writer) override;
+
+ LayerSettings toRenderEngineLayerSettings() override;
+
+ void fillBuffer(std::vector<Color>& expectedColors);
+
+ void setBuffer(std::vector<Color> colors);
+
+ void setDataspace(Dataspace dataspace, const std::shared_ptr<CommandWriterBase>& writer);
+
+ void setToClientComposition(const std::shared_ptr<CommandWriterBase>& writer);
+
+ uint32_t getWidth() const { return mWidth; }
+
+ uint32_t getHeight() const { return mHeight; }
+
+ ::android::Rect getAccessRegion() const { return mAccessRegion; }
+
+ uint32_t getLayerCount() const { return mLayerCount; }
+
+ protected:
+ Composition mComposition;
+ ::android::sp<::android::GraphicBuffer> mGraphicBuffer;
+ TestRenderEngine& mRenderEngine;
+ int32_t mFillFence;
+ uint32_t mWidth;
+ uint32_t mHeight;
+ uint32_t mLayerCount;
+ PixelFormat mPixelFormat;
+ uint32_t mUsage;
+ uint32_t mStride;
+ ::android::Rect mAccessRegion;
+};
+
+class ReadbackHelper {
+ public:
+ static std::string getColorModeString(ColorMode mode);
+
+ static std::string getDataspaceString(Dataspace dataspace);
+
+ static Dataspace getDataspaceForColorMode(ColorMode mode);
+
+ static int32_t GetBytesPerPixel(PixelFormat pixelFormat);
+
+ static void fillBuffer(uint32_t width, uint32_t height, uint32_t stride, void* bufferData,
+ PixelFormat pixelFormat, std::vector<Color> desiredPixelColors);
+
+ static void clearColors(std::vector<Color>& expectedColors, int32_t width, int32_t height,
+ int32_t displayWidth);
+
+ static void fillColorsArea(std::vector<Color>& expectedColors, int32_t stride, Rect area,
+ Color color);
+
+ static bool readbackSupported(const PixelFormat& pixelFormat, const Dataspace& dataspace);
+
+ static const std::vector<ColorMode> colorModes;
+ static const std::vector<Dataspace> dataspaces;
+
+ static void compareColorBuffers(std::vector<Color>& expectedColors, void* bufferData,
+ const int32_t stride, const uint32_t width,
+ const uint32_t height, PixelFormat pixelFormat);
+};
+
+class ReadbackBuffer {
+ public:
+ ReadbackBuffer(int64_t display, const std::shared_ptr<IComposerClient>& client,
+ const ::android::sp<::android::GraphicBuffer>& graphicBuffer, int32_t width,
+ int32_t height, common::PixelFormat pixelFormat, common::Dataspace dataspace);
+
+ void setReadbackBuffer();
+
+ void checkReadbackBuffer(std::vector<Color> expectedColors);
+
+ ::android::sp<::android::GraphicBuffer> allocate();
+
+ protected:
+ uint32_t mWidth;
+ uint32_t mHeight;
+ uint32_t mLayerCount;
+ uint32_t mUsage;
+ uint32_t mStride;
+ PixelFormat mPixelFormat;
+ Dataspace mDataspace;
+ int64_t mDisplay;
+ ::android::sp<::android::GraphicBuffer> mGraphicBuffer;
+ std::shared_ptr<IComposerClient> mComposerClient;
+ ::android::Rect mAccessRegion;
+ native_handle_t mBufferHandle;
+};
+
+} // namespace aidl::android::hardware::graphics::composer3::vts
\ No newline at end of file
diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/vts/functional/composer-vts/include/RenderEngineVts.h b/graphics/composer/aidl/android/hardware/graphics/composer3/vts/functional/composer-vts/include/RenderEngineVts.h
new file mode 100644
index 0000000..eaff6d7
--- /dev/null
+++ b/graphics/composer/aidl/android/hardware/graphics/composer3/vts/functional/composer-vts/include/RenderEngineVts.h
@@ -0,0 +1,71 @@
+/**
+ * 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.
+ */
+#pragma once
+
+// TODO(b/129481165): remove the #pragma below and fix conversion issues
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wconversion"
+
+#include <ReadbackVts.h>
+#include <mapper-vts/2.1/MapperVts.h>
+#include <math/half.h>
+#include <math/vec3.h>
+#include <renderengine/ExternalTexture.h>
+#include <renderengine/RenderEngine.h>
+#include <ui/GraphicBuffer.h>
+#include <ui/GraphicBufferAllocator.h>
+#include <ui/PixelFormat.h>
+#include <ui/Rect.h>
+#include <ui/Region.h>
+
+// TODO(b/129481165): remove the #pragma below and fix conversion issues
+#pragma clang diagnostic pop // ignored "-Wconversion
+
+namespace aidl::android::hardware::graphics::composer3::vts {
+
+using ::android::hardware::graphics::mapper::V2_1::IMapper;
+using ::android::renderengine::DisplaySettings;
+using ::android::renderengine::ExternalTexture;
+using ::android::renderengine::RenderEngineCreationArgs;
+
+class TestRenderEngine {
+ public:
+ static constexpr uint32_t sMaxFrameBufferAcquireBuffers = 2;
+
+ TestRenderEngine(const RenderEngineCreationArgs& args);
+ ~TestRenderEngine();
+
+ void setRenderLayers(std::vector<std::shared_ptr<TestLayer>> layers);
+ void initGraphicBuffer(uint32_t width, uint32_t height, uint32_t layerCount, uint64_t usage);
+ void setDisplaySettings(DisplaySettings& displaySettings) {
+ mDisplaySettings = displaySettings;
+ };
+ void drawLayers();
+ void checkColorBuffer(std::vector<Color>& expectedColors);
+
+ ::android::renderengine::RenderEngine& getInternalRenderEngine() { return *mRenderEngine; }
+
+ private:
+ common::PixelFormat mFormat;
+ std::vector<::android::renderengine::LayerSettings> mCompositionLayers;
+ std::unique_ptr<::android::renderengine::RenderEngine> mRenderEngine;
+ std::vector<::android::renderengine::LayerSettings> mRenderLayers;
+ ::android::sp<::android::GraphicBuffer> mGraphicBuffer;
+
+ DisplaySettings mDisplaySettings;
+};
+
+} // namespace aidl::android::hardware::graphics::composer3::vts
\ No newline at end of file