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