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

Commit 863035d9 authored by Alec Mouri's avatar Alec Mouri Committed by Android (Google) Code Review
Browse files

Merge "Support 10-bit VTS readback" into main

parents 4835bb48 6a000228
Loading
Loading
Loading
Loading
+159 −47
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

#include "ReadbackVts.h"
#include <aidl/android/hardware/graphics/common/BufferUsage.h>
#include <cmath>
#include "RenderEngineVts.h"
#include "renderengine/ExternalTexture.h"
#include "renderengine/impl/ExternalTexture.h"
@@ -106,37 +107,72 @@ LayerSettings TestLayer::toRenderEngineLayerSettings() {
    return layerSettings;
}

int32_t ReadbackHelper::GetBytesPerPixel(common::PixelFormat pixelFormat) {
int32_t ReadbackHelper::GetBitsPerChannel(common::PixelFormat pixelFormat) {
    switch (pixelFormat) {
        case common::PixelFormat::RGBA_1010102:
            return 10;
        case common::PixelFormat::RGBA_8888:
            return 4;
        case common::PixelFormat::RGB_888:
            return 3;
            return 8;
        default:
            return -1;
    }
}

void ReadbackHelper::fillBuffer(uint32_t width, uint32_t height, uint32_t stride, void* bufferData,
int32_t ReadbackHelper::GetAlphaBits(common::PixelFormat pixelFormat) {
    switch (pixelFormat) {
        case common::PixelFormat::RGBA_8888:
            return 8;
        case common::PixelFormat::RGBA_1010102:
            return 2;
        case common::PixelFormat::RGB_888:
            return 0;
        default:
            return -1;
    }
}

void ReadbackHelper::fillBuffer(uint32_t width, uint32_t height, uint32_t stride,
                                int32_t bytesPerPixel, 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);
                pixelFormat == common::PixelFormat::RGBA_8888 ||
                pixelFormat == common::PixelFormat::RGBA_1010102);
    int32_t bitsPerChannel = GetBitsPerChannel(pixelFormat);
    int32_t alphaBits = GetAlphaBits(pixelFormat);
    ASSERT_NE(-1, alphaBits);
    ASSERT_NE(-1, bitsPerChannel);
    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;

    uint32_t maxValue = (1 << bitsPerChannel) - 1;
    uint32_t maxAlphaValue = (1 << alphaBits) - 1;
    for (uint32_t row = 0; row < height; row++) {
        for (uint32_t col = 0; col < width; col++) {
            auto pixel = row * 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>(std::round(255.0f * srcColor.r));
            pixelColor[1] = static_cast<uint8_t>(std::round(255.0f * srcColor.g));
            pixelColor[2] = static_cast<uint8_t>(std::round(255.0f * srcColor.b));
            uint32_t offset = (row * stride + col) * static_cast<uint32_t>(bytesPerPixel);

            uint32_t* pixelStart = (uint32_t*)((uint8_t*)bufferData + offset);

            uint32_t red = static_cast<uint32_t>(std::round(maxValue * srcColor.r));
            uint32_t green = static_cast<uint32_t>(std::round(maxValue * srcColor.g));
            uint32_t blue = static_cast<uint32_t>(std::round(maxValue * srcColor.b));

            if (bytesPerPixel == 4) {
                pixelColor[3] = static_cast<uint8_t>(std::round(255.0f * srcColor.a));
            // Boo we're not word aligned so special case this.
            if (pixelFormat == common::PixelFormat::RGB_888) {
                uint8_t* pixelColor = (uint8_t*)pixelStart;
                pixelColor[0] = static_cast<uint8_t>(red);
                pixelColor[1] = static_cast<uint8_t>(green);
                pixelColor[2] = static_cast<uint8_t>(blue);
            } else {
                uint32_t alpha = static_cast<uint32_t>(std::round(maxAlphaValue * srcColor.a));
                uint32_t color = (alpha << (32 - alphaBits)) |
                                 (blue << (32 - alphaBits - bitsPerChannel)) |
                                 (green << (32 - alphaBits - bitsPerChannel * 2)) |
                                 (red << (32 - alphaBits - bitsPerChannel * 3));
                *pixelStart = color;
            }
        }
    }
@@ -165,7 +201,8 @@ void ReadbackHelper::fillColorsArea(std::vector<Color>& expectedColors, int32_t
bool ReadbackHelper::readbackSupported(const common::PixelFormat& pixelFormat,
                                       const common::Dataspace& dataspace) {
    if (pixelFormat != common::PixelFormat::RGB_888 &&
        pixelFormat != common::PixelFormat::RGBA_8888) {
        pixelFormat != common::PixelFormat::RGBA_8888 &&
        pixelFormat != common::PixelFormat::RGBA_1010102) {
        return false;
    }
    if (std::find(dataspaces.begin(), dataspaces.end(), dataspace) == dataspaces.end()) {
@@ -175,36 +212,110 @@ bool ReadbackHelper::readbackSupported(const common::PixelFormat& pixelFormat,
}

void ReadbackHelper::compareColorBuffers(const std::vector<Color>& expectedColors, void* bufferData,
                                         const uint32_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 * static_cast<int32_t>(stride) + col) * bytesPerPixel;
            uint8_t* pixelColor = (uint8_t*)bufferData + offset;
                                         const uint32_t stride, int32_t bytesPerPixel,
                                         const uint32_t width, const uint32_t height,
                                         common::PixelFormat pixelFormat) {
    int32_t bitsPerChannel = GetBitsPerChannel(pixelFormat);
    int32_t alphaBits = GetAlphaBits(pixelFormat);
    ASSERT_GT(bytesPerPixel, 0);
    ASSERT_NE(-1, alphaBits);
    ASSERT_NE(-1, bitsPerChannel);
    uint32_t maxValue = (1 << bitsPerChannel) - 1;
    uint32_t maxAlphaValue = (1 << alphaBits) - 1;
    for (uint32_t row = 0; row < height; row++) {
        for (uint32_t col = 0; col < width; col++) {
            auto pixel = row * width + col;
            const Color expectedColor = expectedColors[static_cast<size_t>(pixel)];
            ASSERT_EQ(std::round(255.0f * expectedColor.r), pixelColor[0]);
            ASSERT_EQ(std::round(255.0f * expectedColor.g), pixelColor[1]);
            ASSERT_EQ(std::round(255.0f * expectedColor.b), pixelColor[2]);

            uint32_t offset = (row * stride + col) * static_cast<uint32_t>(bytesPerPixel);
            uint32_t* pixelStart = (uint32_t*)((uint8_t*)bufferData + offset);

            uint32_t expectedRed = static_cast<uint32_t>(std::round(maxValue * expectedColor.r));
            uint32_t expectedGreen = static_cast<uint32_t>(std::round(maxValue * expectedColor.g));
            uint32_t expectedBlue = static_cast<uint32_t>(std::round(maxValue * expectedColor.b));

            // Boo we're not word aligned so special case this.
            if (pixelFormat == common::PixelFormat::RGB_888) {
                uint8_t* pixelColor = (uint8_t*)pixelStart;
                ASSERT_EQ(pixelColor[0], static_cast<uint8_t>(expectedRed))
                        << "Red channel mismatch at (" << row << ", " << col << ")";
                ASSERT_EQ(pixelColor[1], static_cast<uint8_t>(expectedGreen))
                        << "Green channel mismatch at (" << row << ", " << col << ")";
                ASSERT_EQ(pixelColor[2], static_cast<uint8_t>(expectedBlue))
                        << "Blue channel mismatch at (" << row << ", " << col << ")";
            } else {
                uint32_t expectedAlpha =
                        static_cast<uint32_t>(std::round(maxAlphaValue * expectedColor.a));

                uint32_t actualRed =
                        (*pixelStart >> (32 - alphaBits - bitsPerChannel * 3)) & maxValue;
                uint32_t actualGreen =
                        (*pixelStart >> (32 - alphaBits - bitsPerChannel * 2)) & maxValue;
                uint32_t actualBlue = (*pixelStart >> (32 - alphaBits - bitsPerChannel)) & maxValue;
                uint32_t actualAlpha = (*pixelStart >> (32 - alphaBits)) & maxAlphaValue;

                ASSERT_EQ(expectedRed, actualRed)
                        << "Red channel mismatch at (" << row << ", " << col << ")";
                ASSERT_EQ(expectedGreen, actualGreen)
                        << "Green channel mismatch at (" << row << ", " << col << ")";
                ASSERT_EQ(expectedBlue, actualBlue)
                        << "Blue channel mismatch at (" << row << ", " << col << ")";
            }
        }
    }
}

void ReadbackHelper::compareColorBuffers(void* expectedBuffer, void* actualBuffer,
                                         const uint32_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++) {
            int offset = (row * static_cast<int32_t>(stride) + col) * bytesPerPixel;
            uint8_t* expectedColor = (uint8_t*)expectedBuffer + offset;
            uint8_t* actualColor = (uint8_t*)actualBuffer + offset;
            ASSERT_EQ(expectedColor[0], actualColor[0]);
            ASSERT_EQ(expectedColor[1], actualColor[1]);
            ASSERT_EQ(expectedColor[2], actualColor[2]);
                                         const uint32_t stride, int32_t bytesPerPixel,
                                         const uint32_t width, const uint32_t height,
                                         common::PixelFormat pixelFormat) {
    int32_t bitsPerChannel = GetBitsPerChannel(pixelFormat);
    int32_t alphaBits = GetAlphaBits(pixelFormat);
    ASSERT_GT(bytesPerPixel, 0);
    ASSERT_NE(-1, alphaBits);
    ASSERT_NE(-1, bitsPerChannel);
    uint32_t maxValue = (1 << bitsPerChannel) - 1;
    uint32_t maxAlphaValue = (1 << alphaBits) - 1;
    for (uint32_t row = 0; row < height; row++) {
        for (uint32_t col = 0; col < width; col++) {
            uint32_t offset = (row * stride + col) * static_cast<uint32_t>(bytesPerPixel);
            uint32_t* expectedStart = (uint32_t*)((uint8_t*)expectedBuffer + offset);
            uint32_t* actualStart = (uint32_t*)((uint8_t*)actualBuffer + offset);

            // Boo we're not word aligned so special case this.
            if (pixelFormat == common::PixelFormat::RGB_888) {
                uint8_t* expectedPixel = (uint8_t*)expectedStart;
                uint8_t* actualPixel = (uint8_t*)actualStart;
                ASSERT_EQ(actualPixel[0], expectedPixel[0])
                        << "Red channel mismatch at (" << row << ", " << col << ")";
                ASSERT_EQ(actualPixel[1], expectedPixel[1])
                        << "Green channel mismatch at (" << row << ", " << col << ")";
                ASSERT_EQ(actualPixel[2], expectedPixel[2])
                        << "Blue channel mismatch at (" << row << ", " << col << ")";
            } else {
                uint32_t expectedRed =
                        (*expectedStart >> (32 - alphaBits - bitsPerChannel * 3)) & maxValue;
                uint32_t expectedGreen =
                        (*expectedStart >> (32 - alphaBits - bitsPerChannel * 2)) & maxValue;
                uint32_t expectedBlue =
                        (*expectedStart >> (32 - alphaBits - bitsPerChannel)) & maxValue;
                uint32_t expectedAlpha = (*expectedStart >> (32 - alphaBits)) & maxAlphaValue;

                uint32_t actualRed =
                        (*actualStart >> (32 - alphaBits - bitsPerChannel * 3)) & maxValue;
                uint32_t actualGreen =
                        (*actualStart >> (32 - alphaBits - bitsPerChannel * 2)) & maxValue;
                uint32_t actualBlue =
                        (*actualStart >> (32 - alphaBits - bitsPerChannel)) & maxValue;
                uint32_t actualAlpha = (*actualStart >> (32 - alphaBits)) & maxAlphaValue;

                ASSERT_EQ(expectedRed, actualRed)
                        << "Red channel mismatch at (" << row << ", " << col << ")";
                ASSERT_EQ(expectedGreen, actualGreen)
                        << "Green channel mismatch at (" << row << ", " << col << ")";
                ASSERT_EQ(expectedBlue, actualBlue)
                        << "Blue channel mismatch at (" << row << ", " << col << ")";
            }
        }
    }
}
@@ -258,12 +369,13 @@ void ReadbackBuffer::checkReadbackBuffer(const std::vector<Color>& expectedColor
    auto status = mGraphicBuffer->lockAsync(mUsage, mAccessRegion, &bufData, dup(bufferFence.get()),
                                            &bytesPerPixel, &bytesPerStride);
    EXPECT_EQ(::android::OK, status);
    ASSERT_TRUE(mPixelFormat == PixelFormat::RGB_888 || mPixelFormat == PixelFormat::RGBA_8888);
    ASSERT_TRUE(mPixelFormat == PixelFormat::RGB_888 || mPixelFormat == PixelFormat::RGBA_8888 ||
                mPixelFormat == PixelFormat::RGBA_1010102);
    const uint32_t stride = (bytesPerPixel > 0 && bytesPerStride > 0)
                                    ? static_cast<uint32_t>(bytesPerStride / bytesPerPixel)
                                    : mGraphicBuffer->getStride();
    ReadbackHelper::compareColorBuffers(expectedColors, bufData, stride, mWidth, mHeight,
                                        mPixelFormat);
    ReadbackHelper::compareColorBuffers(expectedColors, bufData, stride, bytesPerPixel, mWidth,
                                        mHeight, mPixelFormat);
    status = mGraphicBuffer->unlock();
    EXPECT_EQ(::android::OK, status);
}
@@ -353,8 +465,8 @@ void TestBufferLayer::fillBuffer(std::vector<Color>& expectedColors) {
                                    ? static_cast<uint32_t>(bytesPerStride / bytesPerPixel)
                                    : mGraphicBuffer->getStride();
    EXPECT_EQ(::android::OK, status);
    ASSERT_NO_FATAL_FAILURE(ReadbackHelper::fillBuffer(mWidth, mHeight, stride, bufData,
                                                       mPixelFormat, expectedColors));
    ASSERT_NO_FATAL_FAILURE(ReadbackHelper::fillBuffer(mWidth, mHeight, stride, bytesPerPixel,
                                                       bufData, mPixelFormat, expectedColors));

    const auto unlockStatus = mGraphicBuffer->unlockAsync(&mFillFence);
    ASSERT_EQ(::android::OK, unlockStatus);
+9 −6
Original line number Diff line number Diff line
@@ -172,10 +172,12 @@ class ReadbackHelper {

    static Dataspace getDataspaceForColorMode(ColorMode mode);

    static int32_t GetBytesPerPixel(PixelFormat pixelFormat);
    static int32_t GetBitsPerChannel(PixelFormat pixelFormat);
    static int32_t GetAlphaBits(PixelFormat pixelFormat);

    static void fillBuffer(uint32_t width, uint32_t height, uint32_t stride, void* bufferData,
                           PixelFormat pixelFormat, std::vector<Color> desiredPixelColors);
    static void fillBuffer(uint32_t width, uint32_t height, uint32_t stride, int32_t bytesPerPixel,
                           void* bufferData, PixelFormat pixelFormat,
                           std::vector<Color> desiredPixelColors);

    static void clearColors(std::vector<Color>& expectedColors, int32_t width, int32_t height,
                            int32_t displayWidth);
@@ -189,11 +191,12 @@ class ReadbackHelper {
    static const std::vector<Dataspace> dataspaces;

    static void compareColorBuffers(const std::vector<Color>& expectedColors, void* bufferData,
                                    const uint32_t stride, const uint32_t width,
                                    const uint32_t height, PixelFormat pixelFormat);
    static void compareColorBuffers(void* expectedBuffer, void* actualBuffer, const uint32_t stride,
                                    const uint32_t stride, int32_t bytesPerPixel,
                                    const uint32_t width, const uint32_t height,
                                    PixelFormat pixelFormat);
    static void compareColorBuffers(void* expectedBuffer, void* actualBuffer, const uint32_t stride,
                                    int32_t bytesPerPixel, const uint32_t width,
                                    const uint32_t height, PixelFormat pixelFormat);
};

class ReadbackBuffer {
+2 −2
Original line number Diff line number Diff line
@@ -83,7 +83,7 @@ void TestRenderEngine::checkColorBuffer(const std::vector<Color>& expectedColors
    const uint32_t stride = (bytesPerPixel > 0 && bytesPerStride > 0)
                                    ? static_cast<uint32_t>(bytesPerStride / bytesPerPixel)
                                    : mGraphicBuffer->getStride();
    ReadbackHelper::compareColorBuffers(expectedColors, bufferData, stride,
    ReadbackHelper::compareColorBuffers(expectedColors, bufferData, stride, bytesPerPixel,
                                        mGraphicBuffer->getWidth(), mGraphicBuffer->getHeight(),
                                        mFormat);
    ASSERT_EQ(::android::OK, mGraphicBuffer->unlock());
@@ -110,7 +110,7 @@ void TestRenderEngine::checkColorBuffer(const ::android::sp<::android::GraphicBu

    ASSERT_EQ(renderedStride, bufferStride);

    ReadbackHelper::compareColorBuffers(renderedBufferData, bufferData, bufferStride,
    ReadbackHelper::compareColorBuffers(renderedBufferData, bufferData, bufferStride, bytesPerPixel,
                                        mGraphicBuffer->getWidth(), mGraphicBuffer->getHeight(),
                                        mFormat);
    ASSERT_EQ(::android::OK, buffer->unlock());
+13 −7
Original line number Diff line number Diff line
@@ -496,11 +496,14 @@ TEST_P(GraphicsCompositionTest, ClientComposition) {
            const auto& buffer = graphicBuffer->handle;
            void* clientBufData;
            const auto stride = static_cast<uint32_t>(graphicBuffer->stride);
            graphicBuffer->lock(clientUsage, layer->getAccessRegion(), &clientBufData);
            int bytesPerPixel = -1;
            int bytesPerStride = -1;
            graphicBuffer->lock(clientUsage, layer->getAccessRegion(), &clientBufData,
                                &bytesPerPixel, &bytesPerStride);

            ASSERT_NO_FATAL_FAILURE(
                    ReadbackHelper::fillBuffer(layer->getWidth(), layer->getHeight(), stride,
                                               clientBufData, clientFormat, expectedColors));
            ASSERT_NO_FATAL_FAILURE(ReadbackHelper::fillBuffer(
                    layer->getWidth(), layer->getHeight(), stride, bytesPerPixel, clientBufData,
                    clientFormat, expectedColors));
            int32_t clientFence;
            const auto unlockStatus = graphicBuffer->unlockAsync(&clientFence);
            ASSERT_EQ(::android::OK, unlockStatus);
@@ -677,15 +680,18 @@ TEST_P(GraphicsCompositionTest, DeviceAndClientComposition) {
        const auto& buffer = graphicBuffer->handle;

        void* clientBufData;
        int bytesPerPixel = -1;
        int bytesPerStride = -1;
        graphicBuffer->lock(clientUsage, {0, 0, getDisplayWidth(), getDisplayHeight()},
                            &clientBufData);
                            &clientBufData, &bytesPerPixel, &bytesPerStride);

        std::vector<Color> clientColors(
                static_cast<size_t>(getDisplayWidth() * getDisplayHeight()));
        ReadbackHelper::fillColorsArea(clientColors, getDisplayWidth(), clientFrame, RED);
        ASSERT_NO_FATAL_FAILURE(ReadbackHelper::fillBuffer(
                static_cast<uint32_t>(getDisplayWidth()), static_cast<uint32_t>(getDisplayHeight()),
                graphicBuffer->getStride(), clientBufData, clientFormat, clientColors));
                graphicBuffer->getStride(), bytesPerPixel, clientBufData, clientFormat,
                clientColors));
        int32_t clientFence;
        const auto unlockStatus = graphicBuffer->unlockAsync(&clientFence);
        ASSERT_EQ(::android::OK, unlockStatus);