1 /*
2 * Copyright (c) 2021 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 static std::shared_ptr<HdiTestLayer> g_testFreshLayer;
33
34 static const std::vector<std::vector<LayerSettings>> TEST_SINGLE_LAYER = {
35 // one layer display test
36 {
37 {
38 .rectRatio = { 0, 0, 1.0f, 0.125f },
39 .color = RED },
40 },
41 {
42 {
43 .rectRatio = { 0, 0.875f, 1.0f, 0.125f },
44 .color = GREEN },
45 },
46 {
47 {
48 .rectRatio = { 0, 0.0, 1.0f, 1.0f },
49 .color = YELLOW },
50 },
51 };
52
53 static const std::vector<std::vector<LayerSettings>> TEST_MULTILAYER = {
54
55 // three layer displayrect test
56 {
57 {
58 .rectRatio = { 0, 0, 1.0f, 1.0f },
59 .color = RED },
60 {
61 .rectRatio = { 0, 0, 1.0f, 0.125f },
62 .color = GREEN },
63 {
64 .rectRatio = { 0, 0.875f, 1.0f, 0.125f },
65 .color = YELLOW },
66 }
67
68 };
69
70 static const std::vector<std::vector<LayerSettings>> TEST_SCALE = {
71 // scale layer test
72 {
73 {
74 .rectRatio = { 0, 0, 1.0f, 1.0f },
75 .color = RED,
76 .bufferRatio = { 1.5, 1.5 } },
77 },
78 {
79 {
80 .rectRatio = { 0, 0, 1.0f, 0.125f },
81 .color = GREEN,
82 .bufferSize = { 1, 1 } },
83 },
84 {
85 {
86 .rectRatio = { 0, 0.875f, 1.0f, 0.125f },
87 .color = YELLOW,
88 .bufferRatio = { 0.25, 0.25 } },
89 }
90 };
91
92 static const std::vector<std::vector<LayerSettings>> TEST_VIDEO = {
93 // video layer test
94 {
95 {
96 .rectRatio = { 0, 0, 1.0f, 0.125f },
97 .color = GREEN,
98 .compositionType = COMPOSITION_VIDEO },
99 },
100
101 {
102 {
103 .rectRatio = { 0, 0, 1.0f, 1.0f },
104 .color = RED },
105 {
106 .rectRatio = { 0, 0, 1.0f, 1.0f },
107 .color = RED,
108 .compositionType = COMPOSITION_VIDEO },
109 },
110 {
111 {
112 .rectRatio = { 0, 0, 1.0f, 1.0f },
113 .color = RED },
114 {
115 .rectRatio = { 0, 0, 1.0f, 0.125f },
116 .color = GREEN,
117 .compositionType = COMPOSITION_VIDEO },
118 },
119 {
120 {
121 .rectRatio = { 0, 0, 1.0f, 1.0f },
122 .color = RED },
123 {
124 .rectRatio = { 0, 0.875f, 1.0f, 0.125f },
125 .color = YELLOW,
126 .compositionType = COMPOSITION_VIDEO },
127 }
128 };
129
130 static const std::vector<std::vector<LayerSettings>> TEST_ALPHA = {
131 // alpha layer test
132 {
133 {
134 .rectRatio = { 0, 0, 1.0f, 1.0f },
135 .color = RED,
136 .alpha = 0xFF },
137 },
138 {
139 {
140 .rectRatio = { 0, 0, 1.0f, 1.0f },
141 .color = RED,
142 .alpha = 0x55 },
143 },
144 {
145 {
146 .rectRatio = { 0, 0, 1.0f, 1.0f },
147 .color = RED,
148 .alpha = 0x00 },
149 },
150 // RED float will overide, must use green now
151 {
152 {
153 .rectRatio = { 0, 0, 1.0f, 1.0f },
154 .color = GREEN,
155 .alpha = 0xFF,
156 .blendType = BLEND_SRCOVER },
157 },
158 {
159 {
160 .rectRatio = { 0, 0, 1.0f, 1.0f },
161 .color = GREEN,
162 .alpha = 0xA7,
163 .blendType = BLEND_SRCOVER },
164 },
165 {
166 {
167 .rectRatio = { 0, 0, 1.0f, 1.0f },
168 .color = GREEN,
169 .alpha = 0x00,
170 .blendType = BLEND_SRCOVER },
171 },
172 };
173
174 static const std::vector<LayerSettings> TEST_ROTATE = {
175 {
176 .rectRatio = { 0, 0, 1.0f, 1.0f },
177 .color = RED,
178 .rotate = ROTATE_NONE },
179 {
180 .rectRatio = { 0, 0, 1.0f, 1.0f },
181 .color = RED,
182 .rotate = ROTATE_90 },
183 {
184 .rectRatio = { 0, 0, 1.0f, 1.0f },
185 .color = RED,
186 .rotate = ROTATE_180 },
187 {
188 .rectRatio = { 0, 0, 1.0f, 1.0f },
189 .color = RED,
190 .rotate = ROTATE_270 },
191 };
192
GetFirstDisplay()193 static inline std::shared_ptr<HdiTestDisplay> GetFirstDisplay()
194 {
195 return HdiTestDevice::GetInstance().GetFirstDisplay();
196 }
197
CheckComposition(std::vector<LayerSettings> & layers,BufferHandle * clientBuffer,uint32_t checkType=HdiCompositionCheck::CHECK_VERTEX)198 static int32_t CheckComposition(std::vector<LayerSettings> &layers, BufferHandle *clientBuffer,
199 uint32_t checkType = HdiCompositionCheck::CHECK_VERTEX)
200 {
201 DISPLAY_TEST_CHK_RETURN((clientBuffer == nullptr), DISPLAY_NULL_PTR, DISPLAY_TEST_LOGE("client buffer is nullptr"));
202 return HdiCompositionCheck::GetInstance().Check(layers, *clientBuffer, checkType);
203 }
204
CreateTestLayer(LayerSettings setting,uint32_t zorder)205 static std::shared_ptr<HdiTestLayer> CreateTestLayer(LayerSettings setting, uint32_t zorder)
206 {
207 int ret;
208 HdiTestDevice::GetInstance();
209 DISPLAY_TEST_LOGD("color 0x%x", setting.color);
210 std::shared_ptr<HdiTestDisplay> display = HdiTestDevice::GetInstance().GetFirstDisplay();
211 DISPLAY_TEST_CHK_RETURN((display == nullptr), nullptr, DISPLAY_TEST_LOGE("can not get display"));
212
213 std::shared_ptr<HdiTestLayer> layer = display->CreateHdiTestLayer(setting.bufferSize.w, setting.bufferSize.h);
214 DISPLAY_TEST_CHK_RETURN((layer == nullptr), nullptr, DISPLAY_TEST_LOGE("can not create hdi test layer"));
215
216 layer->SetLayerSize(setting.displayRect);
217
218 layer->SetCompType(setting.compositionType);
219
220 if ((setting.alpha >= 0) && (setting.alpha <= 0xff)) { // alpha rang 0x00 ~ 0xff
221 LayerAlpha alpha = { 0 };
222 alpha.gAlpha = setting.alpha;
223 alpha.enGlobalAlpha = true;
224 layer->SetAlpha(alpha);
225 }
226 HdiGrallocBuffer *handle = layer->GetFrontBuffer();
227 DISPLAY_TEST_CHK_RETURN((handle == nullptr), nullptr, DISPLAY_TEST_LOGE("can not get front buffer"));
228 ClearColor(*(handle->Get()), setting.color);
229 ret = layer->SwapFrontToBackQ();
230 DISPLAY_TEST_CHK_RETURN((ret != DISPLAY_SUCCESS), nullptr, DISPLAY_TEST_LOGE("SwapFrontToBackQ failed"));
231 layer->SetZorder(zorder);
232 layer->SetBlendType(setting.blendType);
233 layer->SetTransform(setting.rotate);
234 return layer;
235 }
236
PrepareAndPrensent()237 static int PrepareAndPrensent()
238 {
239 int ret;
240 DISPLAY_TEST_LOGD();
241 std::shared_ptr<HdiTestDisplay> display = HdiTestDevice::GetInstance().GetFirstDisplay();
242 DISPLAY_TEST_CHK_RETURN((display == nullptr), DISPLAY_FAILURE, DISPLAY_TEST_LOGE("can not get display"));
243
244 ret = display->PrepareDisplayLayers();
245 DISPLAY_TEST_CHK_RETURN((ret != DISPLAY_SUCCESS), DISPLAY_FAILURE,
246 DISPLAY_TEST_LOGE("PrepareDisplayLayers failed"));
247
248 ret = display->Commit();
249 DISPLAY_TEST_CHK_RETURN((ret != DISPLAY_SUCCESS), DISPLAY_FAILURE, DISPLAY_TEST_LOGE("Commit failed"));
250 return DISPLAY_SUCCESS;
251 }
252
TestVBlankCallback(unsigned int sequence,uint64_t ns,void * data)253 static void TestVBlankCallback(unsigned int sequence, uint64_t ns, void *data)
254 {
255 static uint64_t lastns;
256 DISPLAY_TEST_LOGD("seq %d ns %" PRId64 " duration %" PRId64 " ns", sequence, ns, (ns - lastns));
257 lastns = ns;
258 VblankCtr::GetInstance().NotifyVblank(sequence, ns, data);
259 }
260
AdjustLayerSettings(std::vector<LayerSettings> & settings,uint32_t w,uint32_t h)261 static void AdjustLayerSettings(std::vector<LayerSettings> &settings, uint32_t w, uint32_t h)
262 {
263 DISPLAY_TEST_LOGD();
264 for (uint32_t i = 0; i < settings.size(); i++) {
265 LayerSettings &setting = settings[i];
266 DISPLAY_TEST_LOGD(" ratio w: %f ratio h: %f", setting.rectRatio.w, setting.rectRatio.h);
267 if ((setting.rectRatio.w > 0.0f) && (setting.rectRatio.h > 0.0f)) {
268 setting.displayRect.h = static_cast<uint32_t>(setting.rectRatio.h * h);
269 setting.displayRect.w = static_cast<uint32_t>(setting.rectRatio.w * w);
270 setting.displayRect.x = static_cast<uint32_t>(setting.rectRatio.x * w);
271 setting.displayRect.y = static_cast<uint32_t>(setting.rectRatio.y * h);
272 DISPLAY_TEST_LOGD("display rect adust form %f %f %f %f to %d %d %d %d ", setting.rectRatio.x,
273 setting.rectRatio.y, setting.rectRatio.w, setting.rectRatio.h, setting.displayRect.x,
274 setting.displayRect.y, setting.displayRect.w, setting.displayRect.h);
275 }
276
277 if ((setting.bufferRatio.h > 0.0f) || (setting.bufferRatio.w > 0.0f)) {
278 setting.bufferSize.h = static_cast<uint32_t>(setting.bufferRatio.h * h);
279 setting.bufferSize.w = static_cast<uint32_t>(setting.bufferRatio.w * w);
280 DISPLAY_TEST_LOGD("buffer szie adjust for %f %f to %d %d", setting.bufferRatio.w, setting.bufferRatio.h,
281 setting.bufferSize.w, setting.bufferSize.h);
282 }
283
284 if ((setting.bufferSize.w == 0) || (setting.bufferSize.h == 0)) {
285 DISPLAY_TEST_LOGD("buffer szie adjust for %d %d to %d %d", setting.bufferSize.w, setting.bufferSize.h,
286 setting.displayRect.w, setting.displayRect.h);
287
288 setting.bufferSize.w = setting.displayRect.w;
289 setting.bufferSize.h = setting.displayRect.h;
290 }
291 }
292 }
293
CreateLayers(std::vector<LayerSettings> & settings)294 static std::vector<std::shared_ptr<HdiTestLayer>> CreateLayers(std::vector<LayerSettings> &settings)
295 {
296 DISPLAY_TEST_LOGD("settings %zd", settings.size());
297 std::vector<std::shared_ptr<HdiTestLayer>> layers;
298 DisplayModeInfo mode = GetFirstDisplay()->GetCurrentMode();
299 AdjustLayerSettings(settings, mode.width, mode.height);
300 for (uint32_t i = 0; i < settings.size(); i++) {
301 LayerSettings setting = settings[i];
302
303 auto layer = CreateTestLayer(setting, i);
304 layers.push_back(layer);
305 }
306
307 return layers;
308 }
309
PresentAndCheck(std::vector<LayerSettings> & layerSettings,uint32_t checkType=HdiCompositionCheck::CHECK_VERTEX)310 static inline void PresentAndCheck(std::vector<LayerSettings> &layerSettings,
311 uint32_t checkType = HdiCompositionCheck::CHECK_VERTEX)
312 {
313 int ret = PrepareAndPrensent();
314 ASSERT_TRUE((ret == DISPLAY_SUCCESS));
315 HdiTestDevice::GetInstance().GetGrallocFuncs().InvalidateCache(GetFirstDisplay()->SnapShot());
316 ret = CheckComposition(layerSettings, GetFirstDisplay()->SnapShot(), checkType);
317 ASSERT_TRUE((ret == DISPLAY_SUCCESS));
318 }
319
TearDown()320 void LayerRotateTest::TearDown()
321 {
322 DISPLAY_TEST_LOGD();
323 HdiTestDevice::GetInstance().Clear();
324 }
325
TearDown()326 void DeviceTest::TearDown()
327 {
328 DISPLAY_TEST_LOGD();
329 HdiTestDevice::GetInstance().Clear();
330 }
331
TearDown()332 void DeviceLayerDisplay::TearDown()
333 {
334 HdiTestDevice::GetInstance().Clear();
335 }
336
NotifyVblank(unsigned int sequence,uint64_t ns,void * data)337 void VblankCtr::NotifyVblank(unsigned int sequence, uint64_t ns, void *data)
338 {
339 DISPLAY_TEST_LOGD();
340 if (data != nullptr) {
341 DISPLAY_TEST_LOGD("sequence = %u, ns = %" PRIu64 "", sequence, ns);
342 }
343 std::unique_lock<std::mutex> lg(mVblankMutex);
344 mHasVblank = true;
345 mVblankCondition.notify_one();
346 DISPLAY_TEST_LOGD();
347 }
348
~VblankCtr()349 VblankCtr::~VblankCtr() {}
350
WaitVblank(uint32_t ms)351 int32_t VblankCtr::WaitVblank(uint32_t ms)
352 {
353 bool ret;
354 DISPLAY_TEST_LOGD();
355 std::unique_lock<std::mutex> lck(mVblankMutex);
356 mHasVblank = false; // must wait next vblank
357 ret = mVblankCondition.wait_for(lck, std::chrono::milliseconds(ms), [=] { return mHasVblank; });
358 DISPLAY_TEST_LOGD();
359 if (!ret) {
360 return DISPLAY_FAILURE;
361 }
362 return DISPLAY_SUCCESS;
363 }
364
TearDown()365 void VblankTest::TearDown()
366 {
367 auto display = HdiTestDevice::GetInstance().GetFirstDisplay();
368 int32_t ret = display->SetDisplayVsyncEnabled(false);
369 if (ret != DISPLAY_SUCCESS) {
370 DISPLAY_TEST_LOGE("vsync disable failed");
371 }
372 VblankCtr::GetInstance().WaitVblank(100); // wait for last vsync 100ms.
373 HdiTestDevice::GetInstance().Clear();
374 }
375
TEST_P(DeviceLayerDisplay,LayerDisplay)376 TEST_P(DeviceLayerDisplay, LayerDisplay)
377 {
378 std::vector<LayerSettings> layerSettings = GetParam();
379 CreateLayers(layerSettings);
380 PresentAndCheck(layerSettings);
381 if (TestParemeter::GetInstance().mTestSleep > 0) {
382 sleep(TestParemeter::GetInstance().mTestSleep);
383 }
384 }
385
TEST_F(DeviceTest,zorder)386 TEST_F(DeviceTest, zorder)
387 {
388 std::vector<LayerSettings> settings = {
389 {
390 .rectRatio = { 0, 0, 1.0f, 1.0f },
391 .color = RED },
392 {
393 .rectRatio = { 0, 0, 1.0f, 0.125f },
394 .color = GREEN },
395 {
396 .rectRatio = { 0, 0.875f, 1.0f, 0.125f },
397 .color = YELLOW },
398 };
399
400 std::vector<std::vector<int>> zorders = {
401 { 3, 2, 1 }, { 1, 3, 2 }, { 3, 1, 2 }, { 1, 2, 3 }, { 2, 1, 3 }, { 9, 100, 3 },
402 };
403 std::vector<std::shared_ptr<HdiTestLayer>> layers = CreateLayers(settings);
404
405 for (const auto &zorderList : zorders) {
406 // adjust the zorder
407 for (uint32_t i = 0; i < zorderList.size(); i++) {
408 settings[i].zorder = zorderList[i];
409 layers[i]->SetZorder(zorderList[i]);
410 }
411 std::vector<LayerSettings> tempSettings = settings;
412 std::sort(tempSettings.begin(), tempSettings.end(),
413 [=](const auto &l, auto const & r) { return l.zorder < r.zorder; });
414 // present and check
415 PresentAndCheck(tempSettings);
416 }
417 HdiTestDevice::GetInstance().Clear();
418 }
419
TEST_P(LayerRotateTest,SplitCheck)420 TEST_P(LayerRotateTest, SplitCheck)
421 {
422 LayerSettings settings = GetParam();
423 std::vector<LayerSettings> layersSetting = { settings };
424 std::vector<uint32_t> splitColors = { RED, GREEN, YELLOW, TRANSPARENT };
425 std::vector<std::shared_ptr<HdiTestLayer>> layers = CreateLayers(layersSetting);
426 ASSERT_TRUE((layers.size() > 0));
427 // split the buffer
428 auto layer = layers[0];
429 HdiGrallocBuffer *handle = layer->GetBackBuffer(); // the backbuffer has not present now
430 ASSERT_TRUE((handle != nullptr));
431 auto splitRects = SplitBuffer(*(handle->Get()), splitColors);
432 ASSERT_TRUE(splitRects.size() == splitColors.size()); // ensure the splitRects size
433 PrepareAndPrensent();
434 // chage the rect and color to clockwise.
435 std::swap(splitColors[2], splitColors[1]);
436 std::swap(splitColors[2], splitColors[3]);
437 std::swap(splitRects[2], splitRects[1]);
438 std::swap(splitRects[2], splitRects[3]);
439
440 // rotation is clockwise,the color will change clockwise, we just change the color start index
441 uint32_t startIndex = 0;
442 switch (settings.rotate) {
443 case ROTATE_90:
444 startIndex = 3; // start form color index 3
445 break;
446 case ROTATE_180:
447 startIndex = 2; // start form color index 2
448 break;
449 case ROTATE_270:
450 startIndex = 1; // start form color index 1
451 break;
452 default:
453 startIndex = 0;
454 break;
455 }
456 std::vector<LayerSettings> layersCheck;
457 for (uint32_t i = 0; i < splitRects.size(); i++) {
458 uint32_t color = splitColors[(i + startIndex) % sizeof(splitColors.size())];
459 layersCheck.push_back({
460 .displayRect = splitRects[i],
461 .color = color });
462 }
463 ASSERT_TRUE((handle != nullptr));
464 /* for rotation may scale the buffer, Near the edge of rect the color will Smooth gradient,
465 so we must use the center to check.
466 */
467 PresentAndCheck(layersCheck, HdiCompositionCheck::CHECK_CENTER);
468 }
469
TEST_F(DeviceTest,crop)470 TEST_F(DeviceTest, crop)
471 {
472 std::vector<LayerSettings> settings = {
473 {
474 .rectRatio = { 0, 0, 1.0f, 1.0f },
475 .color = RED },
476 };
477 std::vector<uint32_t> splitColors = { { RED, GREEN, YELLOW, TRANSPARENT } };
478
479 std::vector<std::shared_ptr<HdiTestLayer>> layers = CreateLayers(settings);
480 ASSERT_TRUE((layers.size() > 0));
481 // split the buffer
482 auto layer = layers[0];
483 HdiGrallocBuffer *handle = layer->GetBackBuffer(); // the backbuffer has not present now
484 ASSERT_TRUE((handle != nullptr));
485 auto splitRects = SplitBuffer(*(handle->Get()), splitColors);
486 PrepareAndPrensent();
487 for (uint32_t i = 0; i < splitRects.size(); i++) {
488 settings[0].color = splitColors[i];
489 layer->SetLayerCrop(splitRects[i]);
490 PresentAndCheck(settings);
491 }
492 }
493
TEST_F(VblankTest,CtrlTest)494 TEST_F(VblankTest, CtrlTest)
495 {
496 int ret;
497 DISPLAY_TEST_LOGD();
498 std::shared_ptr<HdiTestDisplay> display = HdiTestDevice::GetInstance().GetFirstDisplay();
499 ret = display->RegDisplayVBlankCallback(TestVBlankCallback, nullptr);
500 ASSERT_TRUE(ret == DISPLAY_SUCCESS) << "RegDisplayVBlankCallback failed";
501 ret = display->SetDisplayVsyncEnabled(true);
502 ASSERT_TRUE(ret == DISPLAY_SUCCESS) << "SetDisplayVsyncEnabled failed";
503 ret = VblankCtr::GetInstance().WaitVblank(1000); // 1000ms
504 ASSERT_TRUE(ret == DISPLAY_SUCCESS) << "WaitVblank timeout";
505 ret = display->SetDisplayVsyncEnabled(false);
506 ASSERT_TRUE(ret == DISPLAY_SUCCESS) << "SetDisplayVsyncEnabled failed";
507 usleep(100 * 1000); // wait for 100ms avoid the last vsync.
508 ret = VblankCtr::GetInstance().WaitVblank(1000); // 1000ms
509 ASSERT_TRUE(ret != DISPLAY_SUCCESS) << "vblank do not disable";
510 }
511
512 INSTANTIATE_TEST_CASE_P(MultiLayer, DeviceLayerDisplay, ::testing::ValuesIn(TEST_MULTILAYER));
513 INSTANTIATE_TEST_CASE_P(SingleLayer, DeviceLayerDisplay, ::testing::ValuesIn(TEST_SINGLE_LAYER));
514 INSTANTIATE_TEST_CASE_P(ScaleLayer, DeviceLayerDisplay, ::testing::ValuesIn(TEST_SCALE));
515 INSTANTIATE_TEST_CASE_P(VideoLayer, DeviceLayerDisplay, ::testing::ValuesIn(TEST_VIDEO));
516 INSTANTIATE_TEST_CASE_P(LayerAlpha, DeviceLayerDisplay, ::testing::ValuesIn(TEST_ALPHA));
517 INSTANTIATE_TEST_CASE_P(Rotation, LayerRotateTest, ::testing::ValuesIn(TEST_ROTATE));
518
main(int argc,char ** argv)519 int main(int argc, char **argv)
520 {
521 int ret = HdiTestDevice::GetInstance().InitDevice();
522 DISPLAY_TEST_CHK_RETURN((ret != DISPLAY_SUCCESS), DISPLAY_FAILURE, DISPLAY_TEST_LOGE("Init Device Failed"));
523 ::testing::InitGoogleTest(&argc, argv);
524 ret = RUN_ALL_TESTS();
525 auto display = HdiTestDevice::GetInstance().GetFirstDisplay();
526 if (display != nullptr) {
527 // avoid vsync call back affer the destruction of VblankCtr
528 display->SetDisplayVsyncEnabled(false);
529 VblankCtr::GetInstance().WaitVblank(100);
530 }
531 return ret;
532 }
533