1 /*
2  * Copyright 2019 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 <composer-vts/2.2/ReadbackVts.h>
18 #include <composer-vts/2.2/RenderEngineVts.h>
19 #include "renderengine/ExternalTexture.h"
20 
21 namespace android {
22 namespace hardware {
23 namespace graphics {
24 namespace composer {
25 namespace V2_2 {
26 namespace vts {
27 
write(const std::shared_ptr<CommandWriterBase> & writer)28 void TestLayer::write(const std::shared_ptr<CommandWriterBase>& writer) {
29     writer->selectLayer(mLayer);
30     writer->setLayerDisplayFrame(mDisplayFrame);
31     writer->setLayerSourceCrop(mSourceCrop);
32     writer->setLayerZOrder(mZOrder);
33     writer->setLayerSurfaceDamage(mSurfaceDamage);
34     writer->setLayerTransform(mTransform);
35     writer->setLayerPlaneAlpha(mAlpha);
36     writer->setLayerBlendMode(mBlendMode);
37 }
38 
39 const std::vector<ColorMode> ReadbackHelper::colorModes = {ColorMode::SRGB, ColorMode::DISPLAY_P3};
40 const std::vector<Dataspace> ReadbackHelper::dataspaces = {Dataspace::V0_SRGB,
41                                                            Dataspace::DISPLAY_P3};
42 
getColorModeString(ColorMode mode)43 std::string ReadbackHelper::getColorModeString(ColorMode mode) {
44     switch (mode) {
45         case ColorMode::SRGB:
46             return std::string("SRGB");
47         case ColorMode::DISPLAY_P3:
48             return std::string("DISPLAY_P3");
49         default:
50             return std::string("Unsupported color mode for readback");
51     }
52 }
53 
getDataspaceString(Dataspace dataspace)54 std::string ReadbackHelper::getDataspaceString(Dataspace dataspace) {
55     switch (dataspace) {
56         case Dataspace::V0_SRGB:
57             return std::string("V0_SRGB");
58         case Dataspace::DISPLAY_P3:
59             return std::string("DISPLAY_P3");
60         case Dataspace::UNKNOWN:
61             return std::string("UNKNOWN");
62         default:
63             return std::string("Unsupported dataspace for readback");
64     }
65 }
66 
getDataspaceForColorMode(ColorMode mode)67 Dataspace ReadbackHelper::getDataspaceForColorMode(ColorMode mode) {
68     switch (mode) {
69         case ColorMode::DISPLAY_P3:
70             return Dataspace::DISPLAY_P3;
71         case ColorMode::SRGB:
72         default:
73             return Dataspace::UNKNOWN;
74     }
75 }
76 
toRenderEngineLayerSettings()77 LayerSettings TestLayer::toRenderEngineLayerSettings() {
78     LayerSettings layerSettings;
79 
80     layerSettings.alpha = half(mAlpha);
81     layerSettings.disableBlending = mBlendMode == IComposerClient::BlendMode::NONE;
82     layerSettings.geometry.boundaries = 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 mat4 translation = mat4::translate(
87             vec4((mTransform & Transform::FLIP_H ? -mDisplayFrame.right : 0.0f),
88                  (mTransform & Transform::FLIP_V ? -mDisplayFrame.bottom : 0.0f), 0.0f, 1.0f));
89 
90     const mat4 scale = mat4::scale(vec4(mTransform & Transform::FLIP_H ? -1.0f : 1.0f,
91                                         mTransform & Transform::FLIP_V ? -1.0f : 1.0f, 1.0f, 1.0f));
92 
93     layerSettings.geometry.positionTransform = scale * translation;
94 
95     return layerSettings;
96 }
97 
GetBytesPerPixel(PixelFormat pixelFormat)98 int32_t ReadbackHelper::GetBytesPerPixel(PixelFormat pixelFormat) {
99     switch (pixelFormat) {
100         case PixelFormat::RGBA_8888:
101             return 4;
102         case PixelFormat::RGB_888:
103             return 3;
104         default:
105             return -1;
106     }
107 }
108 
fillBuffer(int32_t width,int32_t height,uint32_t stride,void * bufferData,PixelFormat pixelFormat,std::vector<IComposerClient::Color> desiredPixelColors)109 void ReadbackHelper::fillBuffer(int32_t width, int32_t height, uint32_t stride, void* bufferData,
110                                 PixelFormat pixelFormat,
111                                 std::vector<IComposerClient::Color> desiredPixelColors) {
112     ASSERT_TRUE(pixelFormat == PixelFormat::RGB_888 || pixelFormat == PixelFormat::RGBA_8888);
113     int32_t bytesPerPixel = GetBytesPerPixel(pixelFormat);
114     ASSERT_NE(-1, bytesPerPixel);
115     for (int row = 0; row < height; row++) {
116         for (int col = 0; col < width; col++) {
117             int pixel = row * width + col;
118             IComposerClient::Color srcColor = desiredPixelColors[pixel];
119 
120             int offset = (row * stride + col) * bytesPerPixel;
121             uint8_t* pixelColor = (uint8_t*)bufferData + offset;
122             pixelColor[0] = srcColor.r;
123             pixelColor[1] = srcColor.g;
124             pixelColor[2] = srcColor.b;
125 
126             if (bytesPerPixel == 4) {
127                 pixelColor[3] = srcColor.a;
128             }
129         }
130     }
131 }
132 
clearColors(std::vector<IComposerClient::Color> & expectedColors,int32_t width,int32_t height,int32_t displayWidth)133 void ReadbackHelper::clearColors(std::vector<IComposerClient::Color>& expectedColors, int32_t width,
134                                  int32_t height, int32_t displayWidth) {
135     for (int row = 0; row < height; row++) {
136         for (int col = 0; col < width; col++) {
137             int pixel = row * displayWidth + col;
138             expectedColors[pixel] = BLACK;
139         }
140     }
141 }
142 
fillColorsArea(std::vector<IComposerClient::Color> & expectedColors,int32_t stride,IComposerClient::Rect area,IComposerClient::Color color)143 void ReadbackHelper::fillColorsArea(std::vector<IComposerClient::Color>& expectedColors,
144                                     int32_t stride, IComposerClient::Rect area,
145                                     IComposerClient::Color color) {
146     for (int row = area.top; row < area.bottom; row++) {
147         for (int col = area.left; col < area.right; col++) {
148             int pixel = row * stride + col;
149             expectedColors[pixel] = color;
150         }
151     }
152 }
153 
readbackSupported(const PixelFormat & pixelFormat,const Dataspace & dataspace,const Error error)154 bool ReadbackHelper::readbackSupported(const PixelFormat& pixelFormat, const Dataspace& dataspace,
155                                        const Error error) {
156     if (error != Error::NONE) {
157         return false;
158     }
159     // TODO: add support for RGBA_1010102
160     if (pixelFormat != PixelFormat::RGB_888 && pixelFormat != PixelFormat::RGBA_8888) {
161         return false;
162     }
163     if (std::find(dataspaces.begin(), dataspaces.end(), dataspace) == dataspaces.end()) {
164         return false;
165     }
166     return true;
167 }
168 
compareColorBuffers(std::vector<IComposerClient::Color> & expectedColors,void * bufferData,const uint32_t stride,const uint32_t width,const uint32_t height,const PixelFormat pixelFormat)169 void ReadbackHelper::compareColorBuffers(std::vector<IComposerClient::Color>& expectedColors,
170                                          void* bufferData, const uint32_t stride,
171                                          const uint32_t width, const uint32_t height,
172                                          const PixelFormat pixelFormat) {
173     const int32_t bytesPerPixel = ReadbackHelper::GetBytesPerPixel(pixelFormat);
174     ASSERT_NE(-1, bytesPerPixel);
175     for (int row = 0; row < height; row++) {
176         for (int col = 0; col < width; col++) {
177             int pixel = row * width + col;
178             int offset = (row * stride + col) * bytesPerPixel;
179             uint8_t* pixelColor = (uint8_t*)bufferData + offset;
180 
181             ASSERT_EQ(expectedColors[pixel].r, pixelColor[0]);
182             ASSERT_EQ(expectedColors[pixel].g, pixelColor[1]);
183             ASSERT_EQ(expectedColors[pixel].b, pixelColor[2]);
184         }
185     }
186 }
187 
ReadbackBuffer(Display display,const std::shared_ptr<ComposerClient> & client,const std::shared_ptr<Gralloc> & gralloc,uint32_t width,uint32_t height,PixelFormat pixelFormat,Dataspace dataspace)188 ReadbackBuffer::ReadbackBuffer(Display display, const std::shared_ptr<ComposerClient>& client,
189                                const std::shared_ptr<Gralloc>& gralloc, uint32_t width,
190                                uint32_t height, PixelFormat pixelFormat, Dataspace dataspace) {
191     mDisplay = display;
192 
193     mComposerClient = client;
194     mGralloc = gralloc;
195 
196     mPixelFormat = pixelFormat;
197     mDataspace = dataspace;
198 
199     mWidth = width;
200     mHeight = height;
201     mLayerCount = 1;
202     mFormat = mPixelFormat;
203     mUsage = static_cast<uint64_t>(BufferUsage::CPU_READ_OFTEN | BufferUsage::GPU_TEXTURE);
204 
205     mAccessRegion.top = 0;
206     mAccessRegion.left = 0;
207     mAccessRegion.width = width;
208     mAccessRegion.height = height;
209 }
210 
setReadbackBuffer()211 void ReadbackBuffer::setReadbackBuffer() {
212     mBufferHandle.reset(new Gralloc::NativeHandleWrapper(
213             mGralloc->allocate(mWidth, mHeight, mLayerCount, mFormat, mUsage,
214                                /*import*/ true, &mStride)));
215     ASSERT_NE(false, mGralloc->validateBufferSize(mBufferHandle->get(), mWidth, mHeight,
216                                                   mLayerCount, mFormat, mUsage, mStride));
217     ASSERT_NO_FATAL_FAILURE(mComposerClient->setReadbackBuffer(mDisplay, mBufferHandle->get(), -1));
218 }
219 
checkReadbackBuffer(std::vector<IComposerClient::Color> expectedColors)220 void ReadbackBuffer::checkReadbackBuffer(std::vector<IComposerClient::Color> expectedColors) {
221     // lock buffer for reading
222     int32_t fenceHandle;
223     ASSERT_NO_FATAL_FAILURE(mComposerClient->getReadbackBufferFence(mDisplay, &fenceHandle));
224 
225     void* bufData = mGralloc->lock(mBufferHandle->get(), mUsage, mAccessRegion, fenceHandle);
226     ASSERT_TRUE(mPixelFormat == PixelFormat::RGB_888 || mPixelFormat == PixelFormat::RGBA_8888);
227     ReadbackHelper::compareColorBuffers(expectedColors, bufData, mStride, mWidth, mHeight,
228                                         mPixelFormat);
229     int32_t unlockFence = mGralloc->unlock(mBufferHandle->get());
230     if (unlockFence != -1) {
231         sync_wait(unlockFence, -1);
232         close(unlockFence);
233     }
234 }
235 
write(const std::shared_ptr<CommandWriterBase> & writer)236 void TestColorLayer::write(const std::shared_ptr<CommandWriterBase>& writer) {
237     TestLayer::write(writer);
238     writer->setLayerCompositionType(IComposerClient::Composition::SOLID_COLOR);
239     writer->setLayerColor(mColor);
240 }
241 
toRenderEngineLayerSettings()242 LayerSettings TestColorLayer::toRenderEngineLayerSettings() {
243     LayerSettings layerSettings = TestLayer::toRenderEngineLayerSettings();
244 
245     layerSettings.source.solidColor =
246             half3(static_cast<half>(mColor.r) / 255.0, static_cast<half>(mColor.g) / 255.0,
247                   static_cast<half>(mColor.b) / 255.0);
248     layerSettings.alpha = mAlpha * (static_cast<half>(mColor.a) / 255.0);
249     return layerSettings;
250 }
251 
TestBufferLayer(const std::shared_ptr<ComposerClient> & client,const std::shared_ptr<Gralloc> & gralloc,TestRenderEngine & renderEngine,Display display,int32_t width,int32_t height,PixelFormat format,IComposerClient::Composition composition)252 TestBufferLayer::TestBufferLayer(const std::shared_ptr<ComposerClient>& client,
253                                  const std::shared_ptr<Gralloc>& gralloc,
254                                  TestRenderEngine& renderEngine, Display display, int32_t width,
255                                  int32_t height, PixelFormat format,
256                                  IComposerClient::Composition composition)
257     : TestLayer{client, display}, mRenderEngine(renderEngine) {
258     mGralloc = gralloc;
259     mComposition = composition;
260     mWidth = width;
261     mHeight = height;
262     mLayerCount = 1;
263     mFormat = format;
264     mUsage = static_cast<uint64_t>(BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN |
265                                    BufferUsage::COMPOSER_OVERLAY | BufferUsage::GPU_TEXTURE);
266 
267     mAccessRegion.top = 0;
268     mAccessRegion.left = 0;
269     mAccessRegion.width = width;
270     mAccessRegion.height = height;
271 
272     setSourceCrop({0, 0, (float)width, (float)height});
273 }
274 
write(const std::shared_ptr<CommandWriterBase> & writer)275 void TestBufferLayer::write(const std::shared_ptr<CommandWriterBase>& writer) {
276     TestLayer::write(writer);
277     writer->setLayerCompositionType(mComposition);
278     writer->setLayerVisibleRegion(std::vector<IComposerClient::Rect>(1, mDisplayFrame));
279     if (mBufferHandle != nullptr) writer->setLayerBuffer(0, mBufferHandle->get(), mFillFence);
280 }
281 
toRenderEngineLayerSettings()282 LayerSettings TestBufferLayer::toRenderEngineLayerSettings() {
283     LayerSettings layerSettings = TestLayer::toRenderEngineLayerSettings();
284     layerSettings.source.buffer.buffer = std::make_shared<renderengine::ExternalTexture>(
285             new GraphicBuffer(mBufferHandle->get(), GraphicBuffer::CLONE_HANDLE, mWidth, mHeight,
286                               static_cast<int32_t>(mFormat), 1, mUsage, mStride),
287             mRenderEngine.getInternalRenderEngine(),
288             renderengine::ExternalTexture::Usage::READABLE);
289 
290     layerSettings.source.buffer.usePremultipliedAlpha =
291             mBlendMode == IComposerClient::BlendMode::PREMULTIPLIED;
292 
293     const float scaleX = (mSourceCrop.right - mSourceCrop.left) / (mWidth);
294     const float scaleY = (mSourceCrop.bottom - mSourceCrop.top) / (mHeight);
295     const float translateX = mSourceCrop.left / (mWidth);
296     const float translateY = mSourceCrop.top / (mHeight);
297 
298     layerSettings.source.buffer.textureTransform =
299             mat4::translate(vec4(translateX, translateY, 0, 1)) *
300             mat4::scale(vec4(scaleX, scaleY, 1.0, 1.0));
301 
302     return layerSettings;
303 }
304 
fillBuffer(std::vector<IComposerClient::Color> expectedColors)305 void TestBufferLayer::fillBuffer(std::vector<IComposerClient::Color> expectedColors) {
306     void* bufData = mGralloc->lock(mBufferHandle->get(), mUsage, mAccessRegion, -1);
307     ASSERT_NO_FATAL_FAILURE(
308             ReadbackHelper::fillBuffer(mWidth, mHeight, mStride, bufData, mFormat, expectedColors));
309     mFillFence = mGralloc->unlock(mBufferHandle->get());
310     if (mFillFence != -1) {
311         sync_wait(mFillFence, -1);
312         close(mFillFence);
313     }
314 }
315 
setBuffer(std::vector<IComposerClient::Color> colors)316 void TestBufferLayer::setBuffer(std::vector<IComposerClient::Color> colors) {
317     mBufferHandle.reset(new Gralloc::NativeHandleWrapper(
318             mGralloc->allocate(mWidth, mHeight, mLayerCount, mFormat, mUsage,
319                                /*import*/ true, &mStride)));
320     ASSERT_NE(nullptr, mBufferHandle->get());
321     ASSERT_NO_FATAL_FAILURE(fillBuffer(colors));
322     ASSERT_NE(false, mGralloc->validateBufferSize(mBufferHandle->get(), mWidth, mHeight,
323                                                   mLayerCount, mFormat, mUsage, mStride));
324 }
325 
setDataspace(Dataspace dataspace,const std::shared_ptr<CommandWriterBase> & writer)326 void TestBufferLayer::setDataspace(Dataspace dataspace,
327                                    const std::shared_ptr<CommandWriterBase>& writer) {
328     writer->selectLayer(mLayer);
329     writer->setLayerDataspace(dataspace);
330 }
331 
setToClientComposition(const std::shared_ptr<CommandWriterBase> & writer)332 void TestBufferLayer::setToClientComposition(const std::shared_ptr<CommandWriterBase>& writer) {
333     writer->selectLayer(mLayer);
334     writer->setLayerCompositionType(IComposerClient::Composition::CLIENT);
335 }
336 
337 }  // namespace vts
338 }  // namespace V2_2
339 }  // namespace composer
340 }  // namespace graphics
341 }  // namespace hardware
342 }  // namespace android
343