1 /**
2 * Copyright (c) 2021, The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "ReadbackVts.h"
18 #include <aidl/android/hardware/graphics/common/BufferUsage.h>
19 #include "RenderEngineVts.h"
20 #include "renderengine/ExternalTexture.h"
21 #include "renderengine/impl/ExternalTexture.h"
22
23 namespace aidl::android::hardware::graphics::composer3::vts {
24
25 const std::vector<ColorMode> ReadbackHelper::colorModes = {ColorMode::SRGB, ColorMode::DISPLAY_P3};
26 const std::vector<Dataspace> ReadbackHelper::dataspaces = {common::Dataspace::SRGB,
27 common::Dataspace::DISPLAY_P3};
28
write(ComposerClientWriter & writer)29 void TestLayer::write(ComposerClientWriter& writer) {
30 writer.setLayerDisplayFrame(mDisplay, mLayer, mDisplayFrame);
31 writer.setLayerSourceCrop(mDisplay, mLayer, mSourceCrop);
32 writer.setLayerZOrder(mDisplay, mLayer, mZOrder);
33 writer.setLayerSurfaceDamage(mDisplay, mLayer, mSurfaceDamage);
34 writer.setLayerTransform(mDisplay, mLayer, mTransform);
35 writer.setLayerPlaneAlpha(mDisplay, mLayer, mAlpha);
36 writer.setLayerBlendMode(mDisplay, mLayer, mBlendMode);
37 writer.setLayerBrightness(mDisplay, mLayer, mBrightness);
38 writer.setLayerDataspace(mDisplay, mLayer, mDataspace);
39 }
40
getColorModeString(ColorMode mode)41 std::string ReadbackHelper::getColorModeString(ColorMode mode) {
42 switch (mode) {
43 case ColorMode::SRGB:
44 return {"SRGB"};
45 case ColorMode::DISPLAY_P3:
46 return {"DISPLAY_P3"};
47 default:
48 return {"Unsupported color mode for readback"};
49 }
50 }
51
getDataspaceString(common::Dataspace dataspace)52 std::string ReadbackHelper::getDataspaceString(common::Dataspace dataspace) {
53 switch (dataspace) {
54 case common::Dataspace::SRGB:
55 return {"SRGB"};
56 case common::Dataspace::DISPLAY_P3:
57 return {"DISPLAY_P3"};
58 case common::Dataspace::UNKNOWN:
59 return {"UNKNOWN"};
60 default:
61 return {"Unsupported dataspace for readback"};
62 }
63 }
64
getDataspaceForColorMode(ColorMode mode)65 Dataspace ReadbackHelper::getDataspaceForColorMode(ColorMode mode) {
66 switch (mode) {
67 case ColorMode::DISPLAY_P3:
68 return Dataspace::DISPLAY_P3;
69 case ColorMode::SRGB:
70 return Dataspace::SRGB;
71 default:
72 return Dataspace::UNKNOWN;
73 }
74 }
75
toRenderEngineLayerSettings()76 LayerSettings TestLayer::toRenderEngineLayerSettings() {
77 LayerSettings layerSettings;
78
79 layerSettings.alpha = ::android::half(mAlpha);
80 layerSettings.disableBlending = mBlendMode == BlendMode::NONE;
81 layerSettings.source.buffer.isOpaque = mBlendMode == BlendMode::NONE;
82 layerSettings.geometry.boundaries = ::android::FloatRect(
83 static_cast<float>(mDisplayFrame.left), static_cast<float>(mDisplayFrame.top),
84 static_cast<float>(mDisplayFrame.right), static_cast<float>(mDisplayFrame.bottom));
85
86 const ::android::mat4 translation = ::android::mat4::translate(::android::vec4(
87 (static_cast<uint64_t>(mTransform) & static_cast<uint64_t>(Transform::FLIP_H)
88 ? static_cast<float>(-mDisplayFrame.right)
89 : 0.0f),
90 (static_cast<uint64_t>(mTransform) & static_cast<uint64_t>(Transform::FLIP_V)
91 ? static_cast<float>(-mDisplayFrame.bottom)
92 : 0.0f),
93 0.0f, 1.0f));
94
95 const ::android::mat4 scale = ::android::mat4::scale(::android::vec4(
96 static_cast<uint64_t>(mTransform) & static_cast<uint64_t>(Transform::FLIP_H) ? -1.0f
97 : 1.0f,
98 static_cast<uint64_t>(mTransform) & static_cast<uint64_t>(Transform::FLIP_V) ? -1.0f
99 : 1.0f,
100 1.0f, 1.0f));
101
102 layerSettings.geometry.positionTransform = scale * translation;
103 layerSettings.whitePointNits = mWhitePointNits;
104 layerSettings.sourceDataspace = static_cast<::android::ui::Dataspace>(mDataspace);
105
106 return layerSettings;
107 }
108
GetBytesPerPixel(common::PixelFormat pixelFormat)109 int32_t ReadbackHelper::GetBytesPerPixel(common::PixelFormat pixelFormat) {
110 switch (pixelFormat) {
111 case common::PixelFormat::RGBA_8888:
112 return 4;
113 case common::PixelFormat::RGB_888:
114 return 3;
115 default:
116 return -1;
117 }
118 }
119
fillBuffer(uint32_t width,uint32_t height,uint32_t stride,void * bufferData,common::PixelFormat pixelFormat,std::vector<Color> desiredPixelColors)120 void ReadbackHelper::fillBuffer(uint32_t width, uint32_t height, uint32_t stride, void* bufferData,
121 common::PixelFormat pixelFormat,
122 std::vector<Color> desiredPixelColors) {
123 ASSERT_TRUE(pixelFormat == common::PixelFormat::RGB_888 ||
124 pixelFormat == common::PixelFormat::RGBA_8888);
125 int32_t bytesPerPixel = GetBytesPerPixel(pixelFormat);
126 ASSERT_NE(-1, bytesPerPixel);
127 for (int row = 0; row < height; row++) {
128 for (int col = 0; col < width; col++) {
129 auto pixel = row * static_cast<int32_t>(width) + col;
130 Color srcColor = desiredPixelColors[static_cast<size_t>(pixel)];
131
132 int offset = (row * static_cast<int32_t>(stride) + col) * bytesPerPixel;
133 uint8_t* pixelColor = (uint8_t*)bufferData + offset;
134 pixelColor[0] = static_cast<uint8_t>(std::round(255.0f * srcColor.r));
135 pixelColor[1] = static_cast<uint8_t>(std::round(255.0f * srcColor.g));
136 pixelColor[2] = static_cast<uint8_t>(std::round(255.0f * srcColor.b));
137
138 if (bytesPerPixel == 4) {
139 pixelColor[3] = static_cast<uint8_t>(std::round(255.0f * srcColor.a));
140 }
141 }
142 }
143 }
144
clearColors(std::vector<Color> & expectedColors,int32_t width,int32_t height,int32_t displayWidth)145 void ReadbackHelper::clearColors(std::vector<Color>& expectedColors, int32_t width, int32_t height,
146 int32_t displayWidth) {
147 for (int row = 0; row < height; row++) {
148 for (int col = 0; col < width; col++) {
149 int pixel = row * displayWidth + col;
150 expectedColors[static_cast<size_t>(pixel)] = BLACK;
151 }
152 }
153 }
154
fillColorsArea(std::vector<Color> & expectedColors,int32_t stride,Rect area,Color color)155 void ReadbackHelper::fillColorsArea(std::vector<Color>& expectedColors, int32_t stride, Rect area,
156 Color color) {
157 for (int row = area.top; row < area.bottom; row++) {
158 for (int col = area.left; col < area.right; col++) {
159 int pixel = row * stride + col;
160 expectedColors[static_cast<size_t>(pixel)] = color;
161 }
162 }
163 }
164
readbackSupported(const common::PixelFormat & pixelFormat,const common::Dataspace & dataspace)165 bool ReadbackHelper::readbackSupported(const common::PixelFormat& pixelFormat,
166 const common::Dataspace& dataspace) {
167 if (pixelFormat != common::PixelFormat::RGB_888 &&
168 pixelFormat != common::PixelFormat::RGBA_8888) {
169 return false;
170 }
171 if (std::find(dataspaces.begin(), dataspaces.end(), dataspace) == dataspaces.end()) {
172 return false;
173 }
174 return true;
175 }
176
compareColorBuffers(const std::vector<Color> & expectedColors,void * bufferData,const uint32_t stride,const uint32_t width,const uint32_t height,common::PixelFormat pixelFormat)177 void ReadbackHelper::compareColorBuffers(const std::vector<Color>& expectedColors, void* bufferData,
178 const uint32_t stride, const uint32_t width,
179 const uint32_t height, common::PixelFormat pixelFormat) {
180 const int32_t bytesPerPixel = ReadbackHelper::GetBytesPerPixel(pixelFormat);
181 ASSERT_NE(-1, bytesPerPixel);
182 for (int row = 0; row < height; row++) {
183 for (int col = 0; col < width; col++) {
184 auto pixel = row * static_cast<int32_t>(width) + col;
185 int offset = (row * static_cast<int32_t>(stride) + col) * bytesPerPixel;
186 uint8_t* pixelColor = (uint8_t*)bufferData + offset;
187 const Color expectedColor = expectedColors[static_cast<size_t>(pixel)];
188 ASSERT_EQ(std::round(255.0f * expectedColor.r), pixelColor[0]);
189 ASSERT_EQ(std::round(255.0f * expectedColor.g), pixelColor[1]);
190 ASSERT_EQ(std::round(255.0f * expectedColor.b), pixelColor[2]);
191 }
192 }
193 }
194
compareColorBuffers(void * expectedBuffer,void * actualBuffer,const uint32_t stride,const uint32_t width,const uint32_t height,common::PixelFormat pixelFormat)195 void ReadbackHelper::compareColorBuffers(void* expectedBuffer, void* actualBuffer,
196 const uint32_t stride, const uint32_t width,
197 const uint32_t height, common::PixelFormat pixelFormat) {
198 const int32_t bytesPerPixel = ReadbackHelper::GetBytesPerPixel(pixelFormat);
199 ASSERT_NE(-1, bytesPerPixel);
200 for (int row = 0; row < height; row++) {
201 for (int col = 0; col < width; col++) {
202 int offset = (row * static_cast<int32_t>(stride) + col) * bytesPerPixel;
203 uint8_t* expectedColor = (uint8_t*)expectedBuffer + offset;
204 uint8_t* actualColor = (uint8_t*)actualBuffer + offset;
205 ASSERT_EQ(expectedColor[0], actualColor[0]);
206 ASSERT_EQ(expectedColor[1], actualColor[1]);
207 ASSERT_EQ(expectedColor[2], actualColor[2]);
208 }
209 }
210 }
211
ReadbackBuffer(int64_t display,const std::shared_ptr<VtsComposerClient> & client,int32_t width,int32_t height,common::PixelFormat pixelFormat,common::Dataspace dataspace)212 ReadbackBuffer::ReadbackBuffer(int64_t display, const std::shared_ptr<VtsComposerClient>& client,
213 int32_t width, int32_t height, common::PixelFormat pixelFormat,
214 common::Dataspace dataspace)
215 : mComposerClient(client) {
216 mDisplay = display;
217
218 mPixelFormat = pixelFormat;
219 mDataspace = dataspace;
220
221 mWidth = static_cast<uint32_t>(width);
222 mHeight = static_cast<uint32_t>(height);
223 mLayerCount = 1;
224 mUsage = static_cast<uint64_t>(static_cast<uint64_t>(common::BufferUsage::CPU_READ_OFTEN) |
225 static_cast<uint64_t>(common::BufferUsage::GPU_TEXTURE));
226
227 mAccessRegion.top = 0;
228 mAccessRegion.left = 0;
229 mAccessRegion.right = static_cast<int32_t>(width);
230 mAccessRegion.bottom = static_cast<int32_t>(height);
231 }
232
allocateBuffer()233 ::android::sp<::android::GraphicBuffer> ReadbackBuffer::allocateBuffer() {
234 return ::android::sp<::android::GraphicBuffer>::make(
235 mWidth, mHeight, static_cast<::android::PixelFormat>(mPixelFormat), mLayerCount, mUsage,
236 "ReadbackBuffer");
237 }
238
setReadbackBuffer()239 void ReadbackBuffer::setReadbackBuffer() {
240 mGraphicBuffer = allocateBuffer();
241 ASSERT_NE(nullptr, mGraphicBuffer);
242 ASSERT_EQ(::android::OK, mGraphicBuffer->initCheck());
243 const auto& bufferHandle = mGraphicBuffer->handle;
244 ::ndk::ScopedFileDescriptor fence = ::ndk::ScopedFileDescriptor(-1);
245 EXPECT_TRUE(mComposerClient->setReadbackBuffer(mDisplay, bufferHandle, fence).isOk());
246 }
247
checkReadbackBuffer(const std::vector<Color> & expectedColors)248 void ReadbackBuffer::checkReadbackBuffer(const std::vector<Color>& expectedColors) {
249 ASSERT_NE(nullptr, mGraphicBuffer);
250 // lock buffer for reading
251 const auto& [fenceStatus, bufferFence] = mComposerClient->getReadbackBufferFence(mDisplay);
252 EXPECT_TRUE(fenceStatus.isOk());
253
254 int bytesPerPixel = -1;
255 int bytesPerStride = -1;
256 void* bufData = nullptr;
257
258 auto status = mGraphicBuffer->lockAsync(mUsage, mAccessRegion, &bufData, dup(bufferFence.get()),
259 &bytesPerPixel, &bytesPerStride);
260 EXPECT_EQ(::android::OK, status);
261 ASSERT_TRUE(mPixelFormat == PixelFormat::RGB_888 || mPixelFormat == PixelFormat::RGBA_8888);
262 const uint32_t stride = (bytesPerPixel > 0 && bytesPerStride > 0)
263 ? static_cast<uint32_t>(bytesPerStride / bytesPerPixel)
264 : mGraphicBuffer->getStride();
265 ReadbackHelper::compareColorBuffers(expectedColors, bufData, stride, mWidth, mHeight,
266 mPixelFormat);
267 status = mGraphicBuffer->unlock();
268 EXPECT_EQ(::android::OK, status);
269 }
270
getBuffer()271 ::android::sp<::android::GraphicBuffer> ReadbackBuffer::getBuffer() {
272 const auto& [fenceStatus, bufferFence] = mComposerClient->getReadbackBufferFence(mDisplay);
273 EXPECT_TRUE(fenceStatus.isOk());
274 if (bufferFence.get() != -1) {
275 sync_wait(bufferFence.get(), -1);
276 }
277 return mGraphicBuffer;
278 }
279
write(ComposerClientWriter & writer)280 void TestColorLayer::write(ComposerClientWriter& writer) {
281 TestLayer::write(writer);
282 writer.setLayerCompositionType(mDisplay, mLayer, Composition::SOLID_COLOR);
283 writer.setLayerColor(mDisplay, mLayer, mColor);
284 }
285
toRenderEngineLayerSettings()286 LayerSettings TestColorLayer::toRenderEngineLayerSettings() {
287 LayerSettings layerSettings = TestLayer::toRenderEngineLayerSettings();
288
289 layerSettings.source.solidColor = ::android::half3(mColor.r, mColor.g, mColor.b);
290 layerSettings.alpha = mAlpha * mColor.a;
291 return layerSettings;
292 }
293
TestBufferLayer(const std::shared_ptr<VtsComposerClient> & client,TestRenderEngine & renderEngine,int64_t display,uint32_t width,uint32_t height,common::PixelFormat format,ComposerClientWriter & writer,Composition composition)294 TestBufferLayer::TestBufferLayer(const std::shared_ptr<VtsComposerClient>& client,
295 TestRenderEngine& renderEngine, int64_t display, uint32_t width,
296 uint32_t height, common::PixelFormat format,
297 ComposerClientWriter& writer, Composition composition)
298 : TestLayer{client, display, writer}, mRenderEngine(renderEngine) {
299 mComposition = composition;
300 mWidth = width;
301 mHeight = height;
302 mLayerCount = 1;
303 mPixelFormat = format;
304 mUsage = (static_cast<uint64_t>(common::BufferUsage::CPU_READ_OFTEN) |
305 static_cast<uint64_t>(common::BufferUsage::CPU_WRITE_OFTEN) |
306 static_cast<uint64_t>(common::BufferUsage::COMPOSER_OVERLAY) |
307 static_cast<uint64_t>(common::BufferUsage::GPU_TEXTURE));
308
309 mAccessRegion.top = 0;
310 mAccessRegion.left = 0;
311 mAccessRegion.right = static_cast<int32_t>(width);
312 mAccessRegion.bottom = static_cast<int32_t>(height);
313
314 setSourceCrop({0, 0, (float)width, (float)height});
315 }
316
write(ComposerClientWriter & writer)317 void TestBufferLayer::write(ComposerClientWriter& writer) {
318 TestLayer::write(writer);
319 writer.setLayerCompositionType(mDisplay, mLayer, mComposition);
320 writer.setLayerVisibleRegion(mDisplay, mLayer, std::vector<Rect>(1, mDisplayFrame));
321 if (mGraphicBuffer) {
322 writer.setLayerBuffer(mDisplay, mLayer, /*slot*/ 0, mGraphicBuffer->handle, mFillFence);
323 }
324 }
325
toRenderEngineLayerSettings()326 LayerSettings TestBufferLayer::toRenderEngineLayerSettings() {
327 LayerSettings layerSettings = TestLayer::toRenderEngineLayerSettings();
328 layerSettings.source.buffer.buffer =
329 std::make_shared<::android::renderengine::impl::ExternalTexture>(
330 mGraphicBuffer, mRenderEngine.getInternalRenderEngine(),
331 ::android::renderengine::impl::ExternalTexture::Usage::READABLE);
332
333 layerSettings.source.buffer.usePremultipliedAlpha = mBlendMode == BlendMode::PREMULTIPLIED;
334
335 const float scaleX = (mSourceCrop.right - mSourceCrop.left) / (static_cast<float>(mWidth));
336 const float scaleY = (mSourceCrop.bottom - mSourceCrop.top) / (static_cast<float>(mHeight));
337 const float translateX = mSourceCrop.left / (static_cast<float>(mWidth));
338 const float translateY = mSourceCrop.top / (static_cast<float>(mHeight));
339
340 layerSettings.source.buffer.textureTransform =
341 ::android::mat4::translate(::android::vec4(translateX, translateY, 0.0f, 1.0f)) *
342 ::android::mat4::scale(::android::vec4(scaleX, scaleY, 1.0f, 1.0f));
343
344 return layerSettings;
345 }
346
fillBuffer(std::vector<Color> & expectedColors)347 void TestBufferLayer::fillBuffer(std::vector<Color>& expectedColors) {
348 void* bufData;
349 int32_t bytesPerPixel = -1;
350 int32_t bytesPerStride = -1;
351 auto status = mGraphicBuffer->lock(mUsage, &bufData, &bytesPerPixel, &bytesPerStride);
352 const uint32_t stride = (bytesPerPixel > 0 && bytesPerStride > 0)
353 ? static_cast<uint32_t>(bytesPerStride / bytesPerPixel)
354 : mGraphicBuffer->getStride();
355 EXPECT_EQ(::android::OK, status);
356 ASSERT_NO_FATAL_FAILURE(ReadbackHelper::fillBuffer(mWidth, mHeight, stride, bufData,
357 mPixelFormat, expectedColors));
358
359 const auto unlockStatus = mGraphicBuffer->unlockAsync(&mFillFence);
360 ASSERT_EQ(::android::OK, unlockStatus);
361 }
362
setBuffer(std::vector<Color> colors)363 void TestBufferLayer::setBuffer(std::vector<Color> colors) {
364 mGraphicBuffer = allocateBuffer();
365 ASSERT_NE(nullptr, mGraphicBuffer);
366 ASSERT_EQ(::android::OK, mGraphicBuffer->initCheck());
367 ASSERT_NO_FATAL_FAILURE(fillBuffer(colors));
368 }
369
allocateBuffer()370 ::android::sp<::android::GraphicBuffer> TestBufferLayer::allocateBuffer() {
371 return ::android::sp<::android::GraphicBuffer>::make(
372 mWidth, mHeight, static_cast<::android::PixelFormat>(mPixelFormat), mLayerCount, mUsage,
373 "TestBufferLayer");
374 }
375
setToClientComposition(ComposerClientWriter & writer)376 void TestBufferLayer::setToClientComposition(ComposerClientWriter& writer) {
377 writer.setLayerCompositionType(mDisplay, mLayer, Composition::CLIENT);
378 }
379
380 } // namespace aidl::android::hardware::graphics::composer3::vts
381