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