• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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