mirror of
https://github.com/Evolution-X/hardware_interfaces
synced 2026-02-01 05:49:27 +00:00
Merge "Support 10-bit VTS readback" into main
This commit is contained in:
@@ -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);
|
||||
|
||||
if (bytesPerPixel == 4) {
|
||||
pixelColor[3] = static_cast<uint8_t>(std::round(255.0f * srcColor.a));
|
||||
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));
|
||||
|
||||
// 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);
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user