1/*
2 * Copyright (c) 2023-2024 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_test_display.h"
17#include "unistd.h"
18#include "display_test_utils.h"
19#include "hdi_test_device.h"
20namespace OHOS {
21namespace HDI {
22namespace Display {
23namespace TEST {
24using namespace OHOS::HDI::Display::Composer::V1_1;
25HdiTestDisplay::HdiTestDisplay(uint32_t id, sptr<Composer::V1_2::IDisplayComposerInterface> device)
26    : id_(id), device_(device), currentFb_(nullptr)
27{
28}
29
30int32_t HdiTestDisplay::Init()
31{
32    DISPLAY_TEST_LOGE();
33    int ret = device_->GetDisplayCapability(id_, cap_);
34    DISPLAY_TEST_CHK_RETURN((ret != DISPLAY_SUCCESS), DISPLAY_FAILURE, DISPLAY_TEST_LOGE("can not get cap"));
35    DISPLAY_TEST_LOGE("the capablility name %s type : %{public}d phyWidth : %{public}d phyHeight : %{public}d",
36        cap_.name.c_str(), cap_.type, cap_.phyWidth, cap_.phyHeight);
37    // get the modes
38    ret = device_->GetDisplaySupportedModes(id_, modes_);
39    DISPLAY_TEST_CHK_RETURN((ret != DISPLAY_SUCCESS), DISPLAY_FAILURE, DISPLAY_TEST_LOGE("can not get modes"));
40    DISPLAY_TEST_LOGE("the modes size() %{public}zu", modes_.size());
41
42    ret = device_->GetDisplayMode(id_, activeModeId_);
43    DISPLAY_TEST_CHK_RETURN(
44        (ret != DISPLAY_SUCCESS), DISPLAY_FAILURE, DISPLAY_TEST_LOGE("the mode id is : %{public}u", activeModeId_));
45
46    ret = GetModeInfoFromId(activeModeId_, currentMode_);
47    DISPLAY_TEST_CHK_RETURN((ret != DISPLAY_SUCCESS), DISPLAY_FAILURE,
48        DISPLAY_TEST_LOGE("can not get the mode of id : %{public}u", activeModeId_));
49
50    ret = device_->SetDisplayPowerStatus(id_, Composer::V1_0::DispPowerStatus::POWER_STATUS_ON);
51    DISPLAY_TEST_CHK_RETURN((ret != DISPLAY_SUCCESS), DISPLAY_FAILURE,
52        DISPLAY_TEST_LOGE("SetDisplayPowerStatus failed, id_ : %{public}u", id_));
53
54    ret = device_->SetDisplayMode(id_, currentMode_.id);
55    DISPLAY_TEST_CHK_RETURN(
56        (ret != DISPLAY_SUCCESS), DISPLAY_FAILURE, DISPLAY_TEST_LOGE("SetDisplayMode failed, id_ : %{public}u", id_));
57
58    LayerInfo layerinfo = {0};
59    layerinfo.width = currentMode_.width;
60    layerinfo.height = currentMode_.height;
61    layerinfo.pixFormat = Composer::V1_0::PIXEL_FMT_BGRA_8888;
62    const uint32_t CLIENT_LAYER_ID = 0xffffffff; // invalid id
63    clientLayer_ = std::make_unique<HdiTestLayer>(layerinfo, CLIENT_LAYER_ID, id_);
64    ret = clientLayer_->Init();
65    DISPLAY_TEST_CHK_RETURN(
66        (ret != DISPLAY_SUCCESS), DISPLAY_FAILURE, DISPLAY_TEST_LOGE("the client layer can not be created"));
67
68    ret = device_->SetClientBufferCacheCount(id_, clientLayer_->GetLayerBuffercount());
69    DISPLAY_TEST_CHK_RETURN(
70        (ret != DISPLAY_SUCCESS), DISPLAY_FAILURE, DISPLAY_TEST_LOGE("setClientBufferCount error"));
71    return DISPLAY_SUCCESS;
72}
73
74int32_t HdiTestDisplay::GetModeInfoFromId(int32_t id, DisplayModeInfo& modeInfo) const
75{
76    DISPLAY_TEST_LOGE();
77    auto iter = std::find_if (std::begin(modes_), std::end(modes_), [id](const auto& mode) {
78        return mode.id == id;
79    });
80    if (iter != std::end(modes_)) {
81        modeInfo = *iter;
82        DISPLAY_TEST_LOGE("the mode width: %{public}d height : %{public}d freshRate : %{public}u id: %{public}d",
83            iter->width, iter->height, iter->freshRate, iter->id);
84        return DISPLAY_SUCCESS;
85    }
86    DISPLAY_TEST_LOGE("can not find the modeinfo id : %{public}d", id);
87    return DISPLAY_FAILURE;
88}
89
90std::shared_ptr<HdiTestLayer> HdiTestDisplay::CreateHdiTestLayer(LayerInfo& info)
91{
92    DISPLAY_TEST_LOGE();
93    uint32_t layerId = 0;
94    int ret = device_->CreateLayer(id_, info, HdiTestLayer::MAX_BUFFER_COUNT, layerId);
95    DISPLAY_TEST_LOGE("CreateLayer layerId %{public}u", layerId);
96    DISPLAY_TEST_CHK_RETURN((ret != DISPLAY_SUCCESS), nullptr, DISPLAY_TEST_LOGE("layer creat failed"));
97    auto layer = std::make_shared<HdiTestLayer>(info, layerId, id_);
98    ret = layer->Init();
99    DISPLAY_TEST_CHK_RETURN((ret != DISPLAY_SUCCESS), nullptr, DISPLAY_TEST_LOGE("layer init failed"));
100    layerMaps_.emplace(layerId, layer);
101    return layer;
102}
103
104std::shared_ptr<HdiTestLayer> HdiTestDisplay::CreateHdiTestLayer(uint32_t w, uint32_t h)
105{
106    const int32_t BPP = 32;
107
108    LayerInfo info = {w, h, LAYER_TYPE_GRAPHIC, BPP, Composer::V1_0::PIXEL_FMT_RGBA_8888};
109    return CreateHdiTestLayer(info);
110}
111
112int32_t HdiTestDisplay::RefreshLayersCompType()
113{
114    int ret;
115    std::vector<uint32_t> layers;
116    std::vector<int32_t> types;
117    ret = device_->GetDisplayCompChange(id_, layers, types);
118    DISPLAY_TEST_CHK_RETURN((ret != DISPLAY_SUCCESS), DISPLAY_FAILURE,
119        DISPLAY_TEST_LOGE("GetDisplayCompChange get layers and types failed"));
120    DISPLAY_TEST_LOGE("the change numbers %{public}zu, layers size %{public}zu", layers.size(), layers.size());
121    for (uint32_t i = 0; i < layers.size(); i++) {
122        DISPLAY_TEST_LOGE(" the layer id %{public}u ", layers[i]);
123        std::shared_ptr<HdiTestLayer> layer = GetLayerFromId(layers[i]);
124        layer->SetCompType(static_cast<Composer::V1_0::CompositionType>(types[i]));
125    }
126    return DISPLAY_SUCCESS;
127}
128
129int32_t HdiTestDisplay::GetLayersReleaseFence()
130{
131    int ret;
132    std::vector<uint32_t> layers;
133    std::vector<int32_t> fences;
134
135    ret = device_->GetDisplayReleaseFence(id_, layers, fences);
136    DISPLAY_TEST_CHK_RETURN((ret != 0), DISPLAY_FAILURE, DISPLAY_TEST_LOGE("GetDisplayReleaseFence get data failed"));
137    DISPLAY_TEST_LOGE("the release fence numbers %{public}zu, layers size %{public}zu", layers.size(), layers.size());
138    for (uint32_t i = 0; i < layers.size(); i++) {
139        DISPLAY_TEST_LOGE(" the layer id %{public}u, fence: 0x%x", layers[i], fences[i]);
140        std::shared_ptr<HdiTestLayer> layer = GetLayerFromId(layers[i]);
141        layer->SetReleaseFence(fences[i]);
142    }
143    return DISPLAY_SUCCESS;
144}
145
146int32_t HdiTestDisplay::PrepareDisplayLayers()
147{
148    int ret;
149    needFlushFb_ = false;
150    DISPLAY_TEST_LOGE("id : %{public}u  layer size %{public}zu", id_, layerMaps_.size());
151    for (const auto& layerMap : layerMaps_) {
152        ret = layerMap.second->PreparePresent();
153        DISPLAY_TEST_CHK_RETURN((ret != DISPLAY_SUCCESS), DISPLAY_FAILURE,
154            DISPLAY_TEST_LOGE("layer %{public}d Prepare failed", layerMap.first));
155    }
156    ret = device_->PrepareDisplayLayers(id_, needFlushFb_);
157    DISPLAY_TEST_CHK_RETURN((ret != DISPLAY_SUCCESS), DISPLAY_FAILURE,
158        DISPLAY_TEST_LOGE("PrepareDisplayLayers failed display id %{public}u", id_));
159    ret = RefreshLayersCompType();
160    DISPLAY_TEST_CHK_RETURN(
161        (ret != DISPLAY_SUCCESS), DISPLAY_FAILURE, DISPLAY_TEST_LOGE("RefreshLayersCompType failed"));
162    return DISPLAY_SUCCESS;
163}
164
165int32_t HdiTestDisplay::Commit()
166{
167    int32_t fenceFd;
168    int ret;
169    HdiGrallocBuffer* buffer = nullptr;
170    if (needFlushFb_) {
171        ret = clientLayer_->SwapFrontToBackQ();
172        DISPLAY_TEST_CHK_RETURN((ret != DISPLAY_SUCCESS), DISPLAY_FAILURE,
173            DISPLAY_TEST_LOGE("has no front buffer display id %{public}u", id_));
174
175        buffer = clientLayer_->GetBackBuffer();
176        DISPLAY_TEST_CHK_RETURN((buffer == nullptr), DISPLAY_FAILURE, DISPLAY_TEST_LOGE("can not get back buffer"));
177        BufferHandle* handle = buffer->Get();
178        DISPLAY_TEST_CHK_RETURN((handle == nullptr), DISPLAY_FAILURE, DISPLAY_TEST_LOGE("BufferHandle is null"));
179        ClearColor(*handle, 0); // need clear the fb first
180
181        ret = buffer->SetGraphicBuffer([&](const BufferHandle* buffer, uint32_t seqNo) -> int32_t {
182            int32_t result = device_->SetDisplayClientBuffer(id_, buffer, seqNo, -1);
183            DISPLAY_TEST_CHK_RETURN(
184                (result != DISPLAY_SUCCESS), DISPLAY_FAILURE, DISPLAY_TEST_LOGE("set client buffer handle failed"));
185            return DISPLAY_SUCCESS;
186        });
187        currentFb_ = handle;
188        DISPLAY_TEST_CHK_RETURN(
189            (ret != DISPLAY_SUCCESS), DISPLAY_FAILURE, DISPLAY_TEST_LOGE("set client buffer handle failed"));
190    }
191
192    ret = device_->Commit(id_, fenceFd);
193    DISPLAY_TEST_CHK_RETURN(
194        (ret != DISPLAY_SUCCESS), DISPLAY_FAILURE, DISPLAY_TEST_LOGE("commit failed display id %{public}u", id_));
195    ret = GetLayersReleaseFence();
196    DISPLAY_TEST_CHK_RETURN(
197        (ret != DISPLAY_SUCCESS), DISPLAY_FAILURE, DISPLAY_TEST_LOGE("GetLayersReleaseFence failed %{public}u", id_));
198
199    if (needFlushFb_) {
200        DISPLAY_TEST_LOGE("commit out client buffer fence: %{public}d", fenceFd);
201        buffer->SetReleaseFence(fenceFd);
202        ret = clientLayer_->SwapBackToFrontQ();
203    }
204    DISPLAY_TEST_CHK_RETURN(
205        (ret != DISPLAY_SUCCESS), DISPLAY_FAILURE, DISPLAY_TEST_LOGE("has no back buffer display id %{public}u", id_));
206    return DISPLAY_SUCCESS;
207}
208
209int32_t HdiTestDisplay::RegDisplayVBlankCallback(VBlankCallback cb, void* data) const
210{
211    int ret = device_->RegDisplayVBlankCallback(id_, cb, data);
212    return ret;
213}
214
215int32_t HdiTestDisplay::SetDisplayVsyncEnabled(bool enabled) const
216{
217    int ret = device_->SetDisplayVsyncEnabled(id_, enabled);
218    return ret;
219}
220
221std::shared_ptr<HdiTestLayer> HdiTestDisplay::GetLayerFromId(uint32_t id)
222{
223    auto layerMap = layerMaps_.find(id);
224    DISPLAY_TEST_CHK_RETURN(
225        (layerMap == layerMaps_.end()), nullptr, DISPLAY_TEST_LOGE("can not find the layer id : %{public}u", id));
226    return layerMap->second;
227}
228
229void HdiTestDisplay::Clear()
230{
231    DISPLAY_TEST_LOGE();
232    for (auto const& iter : layerMaps_) {
233        uint32_t layerId = iter.first;
234        device_->DestroyLayer(id_, layerId);
235    }
236    layerMaps_.clear();
237    DISPLAY_TEST_LOGE("layerMaps_ size %{public}zu", layerMaps_.size());
238}
239} // namespace TEST
240} // namespace Display
241} // namespace HDI
242} // namespace OHOS
243