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