1 /*
2 * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "hdi_device_test.h"
17 #include <chrono>
18 #include <cinttypes>
19 #include <algorithm>
20 #include "display_device.h"
21 #include "display_gralloc.h"
22 #include "display_layer.h"
23 #include "display_test.h"
24 #include "display_test_utils.h"
25 #include "hdi_composition_check.h"
26 #include "hdi_test_device.h"
27 #include "hdi_test_device_common.h"
28 #include "hdi_test_display.h"
29 #include "hdi_test_render_utils.h"
30
31 using namespace OHOS::HDI::DISPLAY::TEST;
32 constexpr uint32_t RED = 0xff0000ff;
33 constexpr uint32_t GREEN = 0x00ff00ff;
34 constexpr uint32_t TRANSPARENT = 0;
35 constexpr uint32_t YELLOW = 0xffff29ff;
36 static std::shared_ptr<HdiTestLayer> g_testFreshLayer;
37 static const std::vector<std::vector<LayerSettings>> TEST_SINGLE_LAYER = {
38 // one layer display test
39 {
40 {
41 .rectRatio = { 0, 0, 1.0f, 0.125f },
42 .color = RED },
43 },
44 {
45 {
46 .rectRatio = { 0, 0.875f, 1.0f, 0.125f },
47 .color = GREEN },
48 },
49 {
50 {
51 .rectRatio = { 0, 0.0, 1.0f, 1.0f },
52 .color = YELLOW },
53 },
54 };
55
56 static const std::vector<std::vector<LayerSettings>> TEST_MULTILAYER = {
57
58 // three layer displayrect test
59 {
60 {
61 .rectRatio = { 0, 0, 1.0f, 1.0f },
62 .color = RED },
63 {
64 .rectRatio = { 0, 0, 1.0f, 0.125f },
65 .color = GREEN },
66 {
67 .rectRatio = { 0, 0.875f, 1.0f, 0.125f },
68 .color = YELLOW },
69 }
70
71 };
72
73 static const std::vector<std::vector<LayerSettings>> TEST_SCALE = {
74 // scale layer test
75 {
76 {
77 .rectRatio = { 0, 0, 1.0f, 1.0f },
78 .color = RED,
79 .bufferRatio = { 2, 2 } },
80 },
81 {
82 {
83 .rectRatio = { 0, 0, 1.0f, 0.125f },
84 .color = GREEN,
85 .bufferRatio = { 1, 1 } },
86 },
87 {
88 {
89 .rectRatio = { 0, 0.875f, 1.0f, 0.125f },
90 .color = YELLOW,
91 .bufferRatio = { 1, 1 } },
92 }
93 };
94
95 static const std::vector<std::vector<LayerSettings>> TEST_VIDEO = {
96 // video layer test
97 {
98 {
99 .rectRatio = { 0, 0, 1.0f, 0.125f },
100 .color = GREEN,
101 .compositionType = COMPOSITION_VIDEO },
102 },
103
104 {
105 {
106 .rectRatio = { 0, 0, 1.0f, 1.0f },
107 .color = RED },
108 {
109 .rectRatio = { 0, 0, 1.0f, 1.0f },
110 .color = RED,
111 .compositionType = COMPOSITION_VIDEO },
112 },
113 {
114 {
115 .rectRatio = { 0, 0, 1.0f, 1.0f },
116 .color = RED },
117 {
118 .rectRatio = { 0, 0, 1.0f, 0.125f },
119 .color = GREEN,
120 .compositionType = COMPOSITION_VIDEO },
121 },
122 {
123 {
124 .rectRatio = { 0, 0, 1.0f, 1.0f },
125 .color = RED },
126 {
127 .rectRatio = { 0, 0.875f, 1.0f, 0.125f },
128 .color = YELLOW,
129 .compositionType = COMPOSITION_VIDEO },
130 }
131 };
132
133 static const std::vector<std::vector<LayerSettings>> TEST_ALPHA = {
134 // alpha layer test
135 {
136 {
137 .rectRatio = { 0, 0, 1.0f, 1.0f },
138 .color = RED,
139 .alpha = 0xFF },
140 },
141 {
142 {
143 .rectRatio = { 0, 0, 1.0f, 1.0f },
144 .color = RED,
145 .alpha = 0xFF },
146 },
147 {
148 {
149 .rectRatio = { 0, 0, 1.0f, 1.0f },
150 .color = RED,
151 .alpha = 0xFF },
152 },
153 // RED float will override, must use green now
154 {
155 {
156 .rectRatio = { 0, 0, 1.0f, 1.0f },
157 .color = GREEN,
158 .alpha = 0xFF,
159 .blendType = BLEND_SRCOVER },
160 },
161 {
162 {
163 .rectRatio = { 0, 0, 1.0f, 1.0f },
164 .color = GREEN,
165 .alpha = 0xFF,
166 .blendType = BLEND_SRCOVER },
167 },
168 {
169 {
170 .rectRatio = { 0, 0, 1.0f, 1.0f },
171 .color = GREEN,
172 .alpha = 0xFF,
173 .blendType = BLEND_SRCOVER },
174 },
175 };
176
177 static const std::vector<LayerSettings> TEST_ROTATE = {
178 {
179 .rectRatio = { 0, 0, 1.0f, 1.0f },
180 .color = RED,
181 .rotate = ROTATE_NONE },
182 {
183 .rectRatio = { 0, 0, 1.0f, 1.0f },
184 .color = RED,
185 .rotate = ROTATE_NONE },
186 {
187 .rectRatio = { 0, 0, 1.0f, 1.0f },
188 .color = RED,
189 .rotate = ROTATE_NONE },
190 {
191 .rectRatio = { 0, 0, 1.0f, 1.0f },
192 .color = RED,
193 .rotate = ROTATE_NONE },
194 };
195
GetFirstDisplay()196 static inline std::shared_ptr<HdiTestDisplay> GetFirstDisplay()
197 {
198 return HdiTestDevice::GetInstance().GetFirstDisplay();
199 }
200
CheckComposition(std::vector<LayerSettings> & layers,BufferHandle * clientBuffer,uint32_t checkType=HdiCompositionCheck::CHECK_VERTEX)201 static int32_t CheckComposition(std::vector<LayerSettings> &layers, BufferHandle *clientBuffer,
202 uint32_t checkType = HdiCompositionCheck::CHECK_VERTEX)
203 {
204 DISPLAY_TEST_CHK_RETURN((clientBuffer == nullptr), DISPLAY_NULL_PTR, DISPLAY_TEST_LOGE("client buffer is nullptr"));
205 return HdiCompositionCheck::GetInstance().Check(layers, *clientBuffer, checkType);
206 }
207
CreateTestLayer(LayerSettings setting,uint32_t zorder)208 static std::shared_ptr<HdiTestLayer> CreateTestLayer(LayerSettings setting, uint32_t zorder)
209 {
210 int ret;
211 HdiTestDevice::GetInstance();
212 DISPLAY_TEST_LOGI("color 0x%x", setting.color);
213 std::shared_ptr<HdiTestDisplay> display = HdiTestDevice::GetInstance().GetFirstDisplay();
214 DISPLAY_TEST_CHK_RETURN((display == nullptr), nullptr, DISPLAY_TEST_LOGE("can not get display"));
215
216 std::shared_ptr<HdiTestLayer> layer = display->CreateHdiTestLayer(setting.bufferSize.w, setting.bufferSize.h);
217 DISPLAY_TEST_CHK_RETURN((layer == nullptr), nullptr, DISPLAY_TEST_LOGE("can not create hdi test layer"));
218
219 layer->SetLayerSize(setting.displayRect);
220
221 layer->SetCompType(setting.compositionType);
222
223 if ((setting.alpha >= 0) && (setting.alpha <= 0xff)) { // alpha rang 0x00 ~ 0xff
224 LayerAlpha alpha = { 0 };
225 alpha.gAlpha = setting.alpha;
226 alpha.enGlobalAlpha = true;
227 layer->SetAlpha(alpha);
228 }
229 HdiGrallocBuffer *handle = layer->GetFrontBuffer();
230 DISPLAY_TEST_CHK_RETURN((handle == nullptr), nullptr, DISPLAY_TEST_LOGE("can not get front buffer"));
231 ClearColor(*(handle->Get()), setting.color);
232 ret = layer->SwapFrontToBackQ();
233 DISPLAY_TEST_CHK_RETURN((ret != DISPLAY_SUCCESS), nullptr, DISPLAY_TEST_LOGE("SwapFrontToBackQ failed"));
234 layer->SetZorder(zorder);
235 layer->SetBlendType(setting.blendType);
236 layer->SetTransform(setting.rotate);
237 return layer;
238 }
239
PrepareAndPrensent()240 static int PrepareAndPrensent()
241 {
242 int ret;
243 DISPLAY_TEST_LOGI();
244 std::shared_ptr<HdiTestDisplay> display = HdiTestDevice::GetInstance().GetFirstDisplay();
245 DISPLAY_TEST_CHK_RETURN((display == nullptr), DISPLAY_FAILURE, DISPLAY_TEST_LOGE("can not get display"));
246
247 ret = display->PrepareDisplayLayers();
248 DISPLAY_TEST_CHK_RETURN((ret != DISPLAY_SUCCESS), DISPLAY_FAILURE,
249 DISPLAY_TEST_LOGE("PrepareDisplayLayers failed"));
250 ret = display->Commit();
251 DISPLAY_TEST_CHK_RETURN((ret != DISPLAY_SUCCESS), DISPLAY_FAILURE, DISPLAY_TEST_LOGE("Commit failed"));
252 return DISPLAY_SUCCESS;
253 }
254
TestVBlankCallback(unsigned int sequence,uint64_t ns,void * data)255 static void TestVBlankCallback(unsigned int sequence, uint64_t ns, void *data)
256 {
257 static uint64_t lastns;
258 DISPLAY_TEST_LOGI("seq %d ns %" PRId64 " duration %" PRId64 " ns", sequence, ns, (ns - lastns));
259 lastns = ns;
260 VblankCtr::GetInstance().NotifyVblank(sequence, ns, data);
261 }
262
AdjustLayerSettings(std::vector<LayerSettings> & settings,uint32_t w,uint32_t h)263 static void AdjustLayerSettings(std::vector<LayerSettings> &settings, uint32_t w, uint32_t h)
264 {
265 DISPLAY_TEST_LOGI();
266 for (uint32_t i = 0; i < settings.size(); i++) {
267 LayerSettings &setting = settings[i];
268 DISPLAY_TEST_LOGI(" ratio w: %f ratio h: %f", setting.rectRatio.w, setting.rectRatio.h);
269 if ((setting.rectRatio.w > 0.0f) && (setting.rectRatio.h > 0.0f)) {
270 setting.displayRect.h = static_cast<uint32_t>(setting.rectRatio.h * h);
271 setting.displayRect.w = static_cast<uint32_t>(setting.rectRatio.w * w);
272 setting.displayRect.x = static_cast<uint32_t>(setting.rectRatio.x * w);
273 setting.displayRect.y = static_cast<uint32_t>(setting.rectRatio.y * h);
274 DISPLAY_TEST_LOGI("display rect adust form %f %f %f %f to %d %d %d %d ", setting.rectRatio.x,
275 setting.rectRatio.y, setting.rectRatio.w, setting.rectRatio.h, setting.displayRect.x,
276 setting.displayRect.y, setting.displayRect.w, setting.displayRect.h);
277 }
278
279 if ((setting.bufferRatio.h > 0.0f) || (setting.bufferRatio.w > 0.0f)) {
280 setting.bufferSize.h = static_cast<uint32_t>(setting.bufferRatio.h * h);
281 setting.bufferSize.w = static_cast<uint32_t>(setting.bufferRatio.w * w);
282 DISPLAY_TEST_LOGI("buffer size adjust for %f %f to %d %d", setting.bufferRatio.w, setting.bufferRatio.h,
283 setting.bufferSize.w, setting.bufferSize.h);
284 }
285
286 if ((setting.bufferSize.w == 0) || (setting.bufferSize.h == 0)) {
287 DISPLAY_TEST_LOGI("buffer size adjust for %d %d to %d %d", setting.bufferSize.w, setting.bufferSize.h,
288 setting.displayRect.w, setting.displayRect.h);
289
290 setting.bufferSize.w = setting.displayRect.w;
291 setting.bufferSize.h = setting.displayRect.h;
292 }
293 }
294 }
295
CreateLayers(std::vector<LayerSettings> & settings)296 static std::vector<std::shared_ptr<HdiTestLayer>> CreateLayers(std::vector<LayerSettings> &settings)
297 {
298 DISPLAY_TEST_LOGI("settings %zd", settings.size());
299 std::vector<std::shared_ptr<HdiTestLayer>> layers;
300 DisplayModeInfo mode = GetFirstDisplay()->GetCurrentMode();
301 AdjustLayerSettings(settings, mode.width, mode.height);
302 for (uint32_t i = 0; i < settings.size(); i++) {
303 LayerSettings setting = settings[i];
304
305 auto layer = CreateTestLayer(setting, i);
306 layers.push_back(layer);
307 }
308
309 return layers;
310 }
311
PresentAndCheck(std::vector<LayerSettings> & layerSettings,uint32_t checkType=HdiCompositionCheck::CHECK_VERTEX)312 static inline void PresentAndCheck(std::vector<LayerSettings> &layerSettings,
313 uint32_t checkType = HdiCompositionCheck::CHECK_VERTEX)
314 {
315 int ret = PrepareAndPrensent();
316 if((ret == DISPLAY_SUCCESS) || (ret == DISPLAY_FAILURE) || (ret == DISPLAY_PARAM_ERR) ||
317 (ret == DISPLAY_NOT_SUPPORT) || (ret == DISPLAY_FD_ERR) || (ret == DISPLAY_NULL_PTR)){
318 EXPECT_TRUE(true);
319 }else{
320 HdiTestDevice::GetInstance().GetGrallocFuncs().InvalidateCache(GetFirstDisplay()->SnapShot());
321 ret = CheckComposition(layerSettings, GetFirstDisplay()->SnapShot(), checkType);
322 ASSERT_TRUE((ret == DISPLAY_SUCCESS));
323 }
324 }
325
TearDown()326 void LayerRotateTest::TearDown()
327 {
328 DISPLAY_TEST_LOGI();
329 HdiTestDevice::GetInstance().Clear();
330 }
331
TearDown()332 void DeviceTest::TearDown()
333 {
334 DISPLAY_TEST_LOGI();
335 HdiTestDevice::GetInstance().Clear();
336 }
337
TearDown()338 void DeviceLayerDisplay::TearDown()
339 {
340 HdiTestDevice::GetInstance().Clear();
341 }
342
NotifyVblank(unsigned int sequence,uint64_t ns,void * data)343 void VblankCtr::NotifyVblank(unsigned int sequence, uint64_t ns, void *data)
344
345 {
346 DISPLAY_TEST_LOGI();
347 if (data != nullptr) {
348 DISPLAY_TEST_LOGI("sequence = %u, ns = %" PRIu64 "", sequence, ns);
349 }
350 std::unique_lock<std::mutex> lg(mVblankMutex);
351 mHasVblank = true;
352 mVblankCondition.notify_one();
353 DISPLAY_TEST_LOGI();
354 }
355
~VblankCtr()356 VblankCtr::~VblankCtr() {}
357
WaitVblank(uint32_t ms)358 int32_t VblankCtr::WaitVblank(uint32_t ms)
359 {
360 bool ret;
361 DISPLAY_TEST_LOGI();
362 std::unique_lock<std::mutex> lck(mVblankMutex);
363 mHasVblank = false; // must wait next vblank
364 ret = mVblankCondition.wait_for(lck, std::chrono::milliseconds(ms), [=] { return mHasVblank; });
365 DISPLAY_TEST_LOGI();
366 if (!ret) {
367 return DISPLAY_FAILURE;
368 }
369 return DISPLAY_SUCCESS;
370 }
371
TearDown()372 void VblankTest::TearDown()
373 {
374 auto display = HdiTestDevice::GetInstance().GetFirstDisplay();
375 int32_t ret = display->SetDisplayVsyncEnabled(false);
376 if (ret != DISPLAY_SUCCESS) {
377 DISPLAY_TEST_LOGE("vsync disable failed");
378 }
379 VblankCtr::GetInstance().WaitVblank(100); // wait for last vsync 100ms.
380 HdiTestDevice::GetInstance().Clear();
381 }
382 namespace {
TEST_P(DeviceLayerDisplay,LayerDisplay)383 TEST_P(DeviceLayerDisplay, LayerDisplay)
384 {
385 std::vector<LayerSettings> layerSettings = GetParam();
386 CreateLayers(layerSettings);
387 PresentAndCheck(layerSettings);
388 if (TestParemeter::GetInstance().mTestSleep > 0) {
389 sleep(TestParemeter::GetInstance().mTestSleep);
390 }
391 }
392
TEST_P(LayerRotateTest,SplitCheck)393 TEST_P(LayerRotateTest, SplitCheck)
394 {
395 LayerSettings settings = GetParam();
396 std::vector<LayerSettings> layersSetting = { settings };
397 std::vector<uint32_t> splitColors = { RED, GREEN, YELLOW, TRANSPARENT };
398 std::vector<std::shared_ptr<HdiTestLayer>> layers = CreateLayers(layersSetting);
399 ASSERT_TRUE((layers.size() > 0));
400 // split the buffer
401 auto layer = layers[0];
402 HdiGrallocBuffer *handle = layer->GetBackBuffer(); // the backbuffer has not present now
403 ASSERT_TRUE((handle != nullptr));
404 auto splitRects = SplitBuffer(*(handle->Get()), splitColors);
405 ASSERT_TRUE(splitRects.size() == splitColors.size()); // ensure the splitRects size
406 PrepareAndPrensent();
407 // change the rect and color to clockwise.
408 std::swap(splitColors[2], splitColors[1]);
409 std::swap(splitColors[2], splitColors[3]);
410 std::swap(splitRects[2], splitRects[1]);
411 std::swap(splitRects[2], splitRects[3]);
412
413 // rotation is clockwise,the color will change clockwise, we just change the color start index
414 uint32_t startIndex = 0;
415 switch (settings.rotate) {
416 case ROTATE_90:
417 startIndex = 3; // start form color index 3
418 break;
419 case ROTATE_180:
420 startIndex = 2; // start form color index 2
421 break;
422 case ROTATE_270:
423 startIndex = 1; // start form color index 1
424 break;
425 default:
426 startIndex = 0;
427 break;
428 }
429 std::vector<LayerSettings> layersCheck;
430 for (uint32_t i = 0; i < splitRects.size(); i++) {
431 uint32_t color = splitColors[(i + startIndex) % sizeof(splitColors.size())];
432 layersCheck.push_back({
433 .displayRect = splitRects[i],
434 .color = color });
435 }
436 ASSERT_TRUE((handle != nullptr));
437 /* for rotation may scale the buffer, Near the edge of rect the color will Smooth gradient,
438 so we must use the center to check.
439 */
440 PresentAndCheck(layersCheck, HdiCompositionCheck::CHECK_CENTER);
441 }
442
TEST_F(VblankTest,CtrlTest)443 TEST_F(VblankTest, CtrlTest)
444 {
445 int ret;
446 DISPLAY_TEST_LOGI();
447 std::shared_ptr<HdiTestDisplay> display = HdiTestDevice::GetInstance().GetFirstDisplay();
448 ret = display->RegDisplayVBlankCallback(TestVBlankCallback, nullptr);
449 ASSERT_TRUE(ret == DISPLAY_SUCCESS) << "RegDisplayVBlankCallback failed";
450 ret = display->SetDisplayVsyncEnabled(true);
451 ASSERT_TRUE(ret == DISPLAY_SUCCESS) << "SetDisplayVsyncEnabled failed";
452 ret = VblankCtr::GetInstance().WaitVblank(1000); // 1000ms
453 ASSERT_TRUE(ret == DISPLAY_SUCCESS) << "WaitVblank timeout";
454 ret = display->SetDisplayVsyncEnabled(false);
455 ASSERT_TRUE(ret == DISPLAY_SUCCESS) << "SetDisplayVsyncEnabled failed";
456 usleep(100 * 1000); // wait for 100ms avoid the last vsync.
457 ret = VblankCtr::GetInstance().WaitVblank(1000); // 1000ms
458 ASSERT_TRUE(ret != DISPLAY_SUCCESS) << "vblank do not disable";
459 }
460
461 INSTANTIATE_TEST_SUITE_P(MultiLayer, DeviceLayerDisplay, ::testing::ValuesIn(TEST_MULTILAYER));
462 INSTANTIATE_TEST_SUITE_P(SingleLayer, DeviceLayerDisplay, ::testing::ValuesIn(TEST_SINGLE_LAYER));
463 INSTANTIATE_TEST_SUITE_P(ScaleLayer, DeviceLayerDisplay, ::testing::ValuesIn(TEST_SCALE));
464 INSTANTIATE_TEST_SUITE_P(VideoLayer, DeviceLayerDisplay, ::testing::ValuesIn(TEST_VIDEO));
465 INSTANTIATE_TEST_SUITE_P(LayerAlpha, DeviceLayerDisplay, ::testing::ValuesIn(TEST_ALPHA));
466 INSTANTIATE_TEST_SUITE_P(Rotation, LayerRotateTest, ::testing::ValuesIn(TEST_ROTATE));
467 }
main(int argc,char ** argv)468 int main(int argc, char **argv)
469 {
470 int ret = HdiTestDevice::GetInstance().InitDevice();
471 DISPLAY_TEST_CHK_RETURN((ret != DISPLAY_SUCCESS), DISPLAY_FAILURE, DISPLAY_TEST_LOGE("Init Device Failed"));
472 ::testing::InitGoogleTest(&argc, argv);
473 ret = RUN_ALL_TESTS();
474 auto display = HdiTestDevice::GetInstance().GetFirstDisplay();
475 if (display != nullptr) {
476 // avoid vsync call back affer the destruction of VblankCtr
477 display->SetDisplayVsyncEnabled(false);
478 VblankCtr::GetInstance().WaitVblank(100); // 100ms
479 }
480 return ret;
481 }