Clean up Readback test
Readback will be used in RenderEngine testing. Clean up test files and
extract common classes
Bug: 133411821
Test: build, boot, VtsHalGraphicsComposerV2_2TargetTest
Change-Id: I45b4666348ae0137dd2a7825b5cfd627a1e1aa58
diff --git a/graphics/composer/2.2/utils/vts/Android.bp b/graphics/composer/2.2/utils/vts/Android.bp
index c6b524d..4016120 100644
--- a/graphics/composer/2.2/utils/vts/Android.bp
+++ b/graphics/composer/2.2/utils/vts/Android.bp
@@ -19,12 +19,15 @@
defaults: ["hidl_defaults"],
srcs: [
"ComposerVts.cpp",
+ "ReadbackVts.cpp",
],
static_libs: [
"VtsHalHidlTargetTestBase",
"android.hardware.graphics.composer@2.1",
"android.hardware.graphics.composer@2.1-vts",
"android.hardware.graphics.composer@2.2",
+ "android.hardware.graphics.mapper@2.1",
+ "android.hardware.graphics.mapper@2.1-vts",
],
export_static_lib_headers: [
"android.hardware.graphics.composer@2.1-vts",
diff --git a/graphics/composer/2.2/utils/vts/ReadbackVts.cpp b/graphics/composer/2.2/utils/vts/ReadbackVts.cpp
new file mode 100644
index 0000000..8eabaef
--- /dev/null
+++ b/graphics/composer/2.2/utils/vts/ReadbackVts.cpp
@@ -0,0 +1,247 @@
+/*
+ * Copyright 2019 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 <composer-vts/2.2/ReadbackVts.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace composer {
+namespace V2_2 {
+namespace vts {
+
+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);
+}
+
+int32_t ReadbackHelper::GetBytesPerPixel(PixelFormat pixelFormat) {
+ switch (pixelFormat) {
+ case PixelFormat::RGBA_8888:
+ return 4;
+ case PixelFormat::RGB_888:
+ return 3;
+ default:
+ return -1;
+ }
+}
+
+void ReadbackHelper::fillBuffer(int32_t width, int32_t height, uint32_t stride, void* bufferData,
+ PixelFormat pixelFormat,
+ std::vector<IComposerClient::Color> desiredPixelColors) {
+ ASSERT_TRUE(pixelFormat == PixelFormat::RGB_888 || pixelFormat == 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++) {
+ int pixel = row * width + col;
+ IComposerClient::Color srcColor = desiredPixelColors[pixel];
+
+ int offset = (row * stride + col) * bytesPerPixel;
+ uint8_t* pixelColor = (uint8_t*)bufferData + offset;
+ pixelColor[0] = srcColor.r;
+ pixelColor[1] = srcColor.g;
+ pixelColor[2] = srcColor.b;
+
+ if (bytesPerPixel == 4) {
+ pixelColor[3] = srcColor.a;
+ }
+ }
+ }
+}
+
+void ReadbackHelper::clearColors(std::vector<IComposerClient::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[pixel] = BLACK;
+ }
+ }
+}
+
+void ReadbackHelper::fillColorsArea(std::vector<IComposerClient::Color>& expectedColors,
+ int32_t stride, IComposerClient::Rect area,
+ IComposerClient::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[pixel] = color;
+ }
+ }
+}
+
+bool ReadbackHelper::readbackSupported(const PixelFormat& pixelFormat, const Dataspace& dataspace,
+ const Error error) {
+ if (error != Error::NONE) {
+ return false;
+ }
+ // TODO: add support for RGBA_1010102
+ if (pixelFormat != PixelFormat::RGB_888 && pixelFormat != PixelFormat::RGBA_8888) {
+ return false;
+ }
+ if (dataspace != Dataspace::V0_SRGB) {
+ return false;
+ }
+ return true;
+}
+
+ReadbackBuffer::ReadbackBuffer(Display display, const std::shared_ptr<ComposerClient>& client,
+ const std::shared_ptr<Gralloc>& gralloc, uint32_t width,
+ uint32_t height, PixelFormat pixelFormat, Dataspace dataspace) {
+ mDisplay = display;
+
+ mComposerClient = client;
+ mGralloc = gralloc;
+
+ mPixelFormat = pixelFormat;
+ mDataspace = dataspace;
+
+ mInfo.width = width;
+ mInfo.height = height;
+ mInfo.layerCount = 1;
+ mInfo.format = mPixelFormat;
+ mInfo.usage = static_cast<uint64_t>(BufferUsage::CPU_READ_OFTEN | BufferUsage::GPU_TEXTURE);
+
+ mAccessRegion.top = 0;
+ mAccessRegion.left = 0;
+ mAccessRegion.width = width;
+ mAccessRegion.height = height;
+}
+
+ReadbackBuffer::~ReadbackBuffer() {
+ if (mBufferHandle != nullptr) {
+ mGralloc->freeBuffer(mBufferHandle);
+ }
+}
+
+void ReadbackBuffer::setReadbackBuffer() {
+ if (mBufferHandle != nullptr) {
+ mGralloc->freeBuffer(mBufferHandle);
+ mBufferHandle = nullptr;
+ }
+ mBufferHandle = mGralloc->allocate(mInfo, /*import*/ true, &mStride);
+ ASSERT_NE(false, mGralloc->validateBufferSize(mBufferHandle, mInfo, mStride));
+ ASSERT_NO_FATAL_FAILURE(mComposerClient->setReadbackBuffer(mDisplay, mBufferHandle, -1));
+}
+
+void ReadbackBuffer::checkReadbackBuffer(std::vector<IComposerClient::Color> expectedColors) {
+ // lock buffer for reading
+ int32_t fenceHandle;
+ ASSERT_NO_FATAL_FAILURE(mComposerClient->getReadbackBufferFence(mDisplay, &fenceHandle));
+
+ void* bufData = mGralloc->lock(mBufferHandle, mInfo.usage, mAccessRegion, fenceHandle);
+ ASSERT_TRUE(mPixelFormat == PixelFormat::RGB_888 || mPixelFormat == PixelFormat::RGBA_8888);
+ int32_t bytesPerPixel = ReadbackHelper::GetBytesPerPixel(mPixelFormat);
+ ASSERT_NE(-1, bytesPerPixel);
+ for (int row = 0; row < mInfo.height; row++) {
+ for (int col = 0; col < mInfo.width; col++) {
+ int pixel = row * mInfo.width + col;
+ int offset = (row * mStride + col) * bytesPerPixel;
+ uint8_t* pixelColor = (uint8_t*)bufData + offset;
+
+ ASSERT_EQ(expectedColors[pixel].r, pixelColor[0]);
+ ASSERT_EQ(expectedColors[pixel].g, pixelColor[1]);
+ ASSERT_EQ(expectedColors[pixel].b, pixelColor[2]);
+ }
+ }
+ int32_t unlockFence = mGralloc->unlock(mBufferHandle);
+ if (unlockFence != -1) {
+ sync_wait(unlockFence, -1);
+ close(unlockFence);
+ }
+}
+
+void TestColorLayer::write(const std::shared_ptr<CommandWriterBase>& writer) {
+ TestLayer::write(writer);
+ writer->setLayerCompositionType(IComposerClient::Composition::SOLID_COLOR);
+ writer->setLayerColor(mColor);
+}
+
+TestBufferLayer::TestBufferLayer(const std::shared_ptr<ComposerClient>& client,
+ const std::shared_ptr<Gralloc>& gralloc, Display display,
+ int32_t width, int32_t height, PixelFormat format,
+ IComposerClient::Composition composition)
+ : TestLayer{client, display} {
+ mGralloc = gralloc;
+ mComposition = composition;
+ mInfo.width = width;
+ mInfo.height = height;
+ mInfo.layerCount = 1;
+ mInfo.format = format;
+ mInfo.usage = static_cast<uint64_t>(BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN |
+ BufferUsage::COMPOSER_OVERLAY);
+
+ mAccessRegion.top = 0;
+ mAccessRegion.left = 0;
+ mAccessRegion.width = width;
+ mAccessRegion.height = height;
+
+ setSourceCrop({0, 0, (float)width, (float)height});
+}
+
+TestBufferLayer::~TestBufferLayer() {
+ if (mBufferHandle != nullptr) {
+ mGralloc->freeBuffer(mBufferHandle);
+ }
+}
+
+void TestBufferLayer::write(const std::shared_ptr<CommandWriterBase>& writer) {
+ TestLayer::write(writer);
+ writer->setLayerCompositionType(mComposition);
+ writer->setLayerDataspace(Dataspace::UNKNOWN);
+ writer->setLayerVisibleRegion(std::vector<IComposerClient::Rect>(1, mDisplayFrame));
+ if (mBufferHandle != nullptr) writer->setLayerBuffer(0, mBufferHandle, mFillFence);
+}
+
+void TestBufferLayer::fillBuffer(std::vector<IComposerClient::Color> expectedColors) {
+ void* bufData = mGralloc->lock(mBufferHandle, mInfo.usage, mAccessRegion, -1);
+ ASSERT_NO_FATAL_FAILURE(ReadbackHelper::fillBuffer(mInfo.width, mInfo.height, mStride, bufData,
+ mInfo.format, expectedColors));
+ mFillFence = mGralloc->unlock(mBufferHandle);
+ if (mFillFence != -1) {
+ sync_wait(mFillFence, -1);
+ close(mFillFence);
+ }
+}
+void TestBufferLayer::setBuffer(std::vector<IComposerClient::Color> colors) {
+ if (mBufferHandle != nullptr) {
+ mGralloc->freeBuffer(mBufferHandle);
+ mBufferHandle = nullptr;
+ }
+ mBufferHandle = mGralloc->allocate(mInfo, /*import*/ true, &mStride);
+ ASSERT_NE(nullptr, mBufferHandle);
+ ASSERT_NO_FATAL_FAILURE(fillBuffer(colors));
+ ASSERT_NE(false, mGralloc->validateBufferSize(mBufferHandle, mInfo, mStride));
+}
+
+void TestBufferLayer::setToClientComposition(const std::shared_ptr<CommandWriterBase>& writer) {
+ writer->selectLayer(mLayer);
+ writer->setLayerCompositionType(IComposerClient::Composition::CLIENT);
+}
+
+} // namespace vts
+} // namespace V2_2
+} // namespace composer
+} // namespace graphics
+} // namespace hardware
+} // namespace android
diff --git a/graphics/composer/2.2/utils/vts/include/composer-vts/2.2/ReadbackVts.h b/graphics/composer/2.2/utils/vts/include/composer-vts/2.2/ReadbackVts.h
new file mode 100644
index 0000000..9ce4e39
--- /dev/null
+++ b/graphics/composer/2.2/utils/vts/include/composer-vts/2.2/ReadbackVts.h
@@ -0,0 +1,175 @@
+/*
+ * Copyright 2019 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 <android-base/unique_fd.h>
+#include <android/hardware/graphics/composer/2.2/IComposerClient.h>
+#include <composer-command-buffer/2.2/ComposerCommandBuffer.h>
+#include <composer-vts/2.1/GraphicsComposerCallback.h>
+#include <composer-vts/2.1/TestCommandReader.h>
+#include <composer-vts/2.2/ComposerVts.h>
+#include <mapper-vts/2.1/MapperVts.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace composer {
+namespace V2_2 {
+namespace vts {
+
+using android::hardware::hidl_handle;
+using common::V1_1::BufferUsage;
+using common::V1_1::Dataspace;
+using common::V1_1::PixelFormat;
+using mapper::V2_1::IMapper;
+using mapper::V2_1::vts::Gralloc;
+using V2_1::Display;
+using V2_1::Layer;
+using V2_1::vts::TestCommandReader;
+
+static const IComposerClient::Color BLACK = {0, 0, 0, 0xff};
+static const IComposerClient::Color RED = {0xff, 0, 0, 0xff};
+static const IComposerClient::Color TRANSLUCENT_RED = {0xff, 0, 0, 0x33};
+static const IComposerClient::Color GREEN = {0, 0xff, 0, 0xff};
+static const IComposerClient::Color BLUE = {0, 0, 0xff, 0xff};
+
+class TestLayer {
+ public:
+ TestLayer(const std::shared_ptr<ComposerClient>& client, Display display)
+ : mLayer(client->createLayer(display, kBufferSlotCount)), mComposerClient(client) {}
+
+ // 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);
+
+ void setDisplayFrame(IComposerClient::Rect frame) { mDisplayFrame = frame; }
+ void setSourceCrop(IComposerClient::FRect crop) { mSourceCrop = crop; }
+ void setZOrder(uint32_t z) { mZOrder = z; }
+
+ void setSurfaceDamage(std::vector<IComposerClient::Rect> surfaceDamage) {
+ mSurfaceDamage = surfaceDamage;
+ }
+
+ void setTransform(Transform transform) { mTransform = transform; }
+ void setAlpha(float alpha) { mAlpha = alpha; }
+ void setBlendMode(IComposerClient::BlendMode blendMode) { mBlendMode = blendMode; }
+
+ static constexpr uint32_t kBufferSlotCount = 64;
+
+ IComposerClient::Rect mDisplayFrame = {0, 0, 0, 0};
+ uint32_t mZOrder = 0;
+ std::vector<IComposerClient::Rect> mSurfaceDamage;
+ Transform mTransform = static_cast<Transform>(0);
+ IComposerClient::FRect mSourceCrop = {0, 0, 0, 0};
+ float mAlpha = 1.0;
+ IComposerClient::BlendMode mBlendMode = IComposerClient::BlendMode::NONE;
+
+ protected:
+ Layer mLayer;
+
+ private:
+ std::shared_ptr<ComposerClient> const mComposerClient;
+};
+
+class TestColorLayer : public TestLayer {
+ public:
+ TestColorLayer(const std::shared_ptr<ComposerClient>& client, Display display)
+ : TestLayer{client, display} {}
+
+ void write(const std::shared_ptr<CommandWriterBase>& writer) override;
+
+ void setColor(IComposerClient::Color color) { mColor = color; }
+
+ private:
+ IComposerClient::Color mColor = {0xff, 0xff, 0xff, 0xff};
+};
+
+class TestBufferLayer : public TestLayer {
+ public:
+ TestBufferLayer(
+ const std::shared_ptr<ComposerClient>& client, const std::shared_ptr<Gralloc>& gralloc,
+ Display display, int32_t width, int32_t height, PixelFormat format,
+ IComposerClient::Composition composition = IComposerClient::Composition::DEVICE);
+
+ ~TestBufferLayer();
+
+ void write(const std::shared_ptr<CommandWriterBase>& writer) override;
+
+ void fillBuffer(std::vector<IComposerClient::Color> expectedColors);
+
+ void setBuffer(std::vector<IComposerClient::Color> colors);
+
+ void setToClientComposition(const std::shared_ptr<CommandWriterBase>& writer);
+
+ IMapper::BufferDescriptorInfo mInfo;
+ IMapper::Rect mAccessRegion;
+ uint32_t mStride;
+
+ protected:
+ IComposerClient::Composition mComposition;
+ std::shared_ptr<Gralloc> mGralloc;
+ int32_t mFillFence;
+ const native_handle_t* mBufferHandle = nullptr;
+};
+
+class ReadbackHelper : public ::testing::VtsHalHidlTargetTestBase {
+ public:
+ static int32_t GetBytesPerPixel(PixelFormat pixelFormat);
+
+ static void fillBuffer(int32_t width, int32_t height, uint32_t stride, void* bufferData,
+ PixelFormat pixelFormat,
+ std::vector<IComposerClient::Color> desiredPixelColors);
+
+ static void clearColors(std::vector<IComposerClient::Color>& expectedColors, int32_t width,
+ int32_t height, int32_t displayWidth);
+
+ static void fillColorsArea(std::vector<IComposerClient::Color>& expectedColors, int32_t stride,
+ IComposerClient::Rect area, IComposerClient::Color color);
+
+ static bool readbackSupported(const PixelFormat& pixelFormat, const Dataspace& dataspace,
+ const Error error);
+};
+
+class ReadbackBuffer {
+ public:
+ ReadbackBuffer(Display display, const std::shared_ptr<ComposerClient>& client,
+ const std::shared_ptr<Gralloc>& gralloc, uint32_t width, uint32_t height,
+ PixelFormat pixelFormat, Dataspace dataspace);
+ ~ReadbackBuffer();
+
+ void setReadbackBuffer();
+
+ void checkReadbackBuffer(std::vector<IComposerClient::Color> expectedColors);
+
+ protected:
+ IMapper::BufferDescriptorInfo mInfo;
+ IMapper::Rect mAccessRegion;
+ uint32_t mStride;
+ const native_handle_t* mBufferHandle = nullptr;
+ PixelFormat mPixelFormat;
+ Dataspace mDataspace;
+ Display mDisplay;
+ std::shared_ptr<Gralloc> mGralloc;
+ std::shared_ptr<ComposerClient> mComposerClient;
+};
+
+} // namespace vts
+} // namespace V2_2
+} // namespace composer
+} // namespace graphics
+} // namespace hardware
+} // namespace android