Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit bab8ba92 authored by ramindani's avatar ramindani
Browse files

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
parent dcfe3a8b
Loading
Loading
Loading
Loading
+14 −1
Original line number Diff line number Diff line
@@ -28,20 +28,29 @@ cc_test {
    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 @@ cc_test {
        "android.hardware.graphics.mapper@3.0-vts",
        "android.hardware.graphics.mapper@4.0-vts",
        "libaidlcommonsupport",
        "libgtest",
        "librenderengine",
        "libshaders",
        "libtonemap",
    ],
    cflags: [
        "-Wconversion",
+1360 −0

File added.

Preview size limit exceeded, changes collapsed.

+14 −0
Original line number Diff line number Diff line
@@ -29,6 +29,8 @@ cc_library_static {
    srcs: [
        "GraphicsComposerCallback.cpp",
        "TestCommandReader.cpp",
        "ReadbackVts.cpp",
        "RenderEngineVts.cpp",
    ],
    header_libs: [
        "android.hardware.graphics.composer3-command-buffer",
@@ -38,20 +40,32 @@ cc_library_static {
        "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",
+360 −0
Original line number Diff line number Diff line
/**
 * 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
+89 −0
Original line number Diff line number Diff line
/**
 * 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
Loading