1e9297d28Sopenharmony_ci/*
2e9297d28Sopenharmony_ci * Copyright (c) 2021 Huawei Device Co., Ltd.
3e9297d28Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4e9297d28Sopenharmony_ci * you may not use this file except in compliance with the License.
5e9297d28Sopenharmony_ci * You may obtain a copy of the License at
6e9297d28Sopenharmony_ci *
7e9297d28Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
8e9297d28Sopenharmony_ci *
9e9297d28Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10e9297d28Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11e9297d28Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12e9297d28Sopenharmony_ci * See the License for the specific language governing permissions and
13e9297d28Sopenharmony_ci * limitations under the License.
14e9297d28Sopenharmony_ci */
15e9297d28Sopenharmony_ci
16e9297d28Sopenharmony_ci#include "hello_composer.h"
17e9297d28Sopenharmony_ci
18e9297d28Sopenharmony_ci#include <vsync_generator.h>
19e9297d28Sopenharmony_ci#include <vsync_controller.h>
20e9297d28Sopenharmony_ci#include <vsync_distributor.h>
21e9297d28Sopenharmony_ci#include <vsync_receiver.h>
22e9297d28Sopenharmony_ci#include <securec.h>
23e9297d28Sopenharmony_ci#include <sync_fence.h>
24e9297d28Sopenharmony_ci
25e9297d28Sopenharmony_ciusing namespace OHOS;
26e9297d28Sopenharmony_ciusing namespace OHOS::Rosen;
27e9297d28Sopenharmony_ci
28e9297d28Sopenharmony_cinamespace {
29e9297d28Sopenharmony_ci#define LOGI(fmt, ...) ::OHOS::HiviewDFX::HiLog::Info(            \
30e9297d28Sopenharmony_ci    ::OHOS::HiviewDFX::HiLogLabel {LOG_CORE, 0, "HelloComposer"}, \
31e9297d28Sopenharmony_ci    "%{public}s: " fmt, __func__, ##__VA_ARGS__)
32e9297d28Sopenharmony_ci
33e9297d28Sopenharmony_ci#define LOGE(fmt, ...) ::OHOS::HiviewDFX::HiLog::Error(           \
34e9297d28Sopenharmony_ci    ::OHOS::HiviewDFX::HiLogLabel {LOG_CORE, 0, "HelloComposer"}, \
35e9297d28Sopenharmony_ci    "%{public}s: " fmt, __func__, ##__VA_ARGS__)
36e9297d28Sopenharmony_ci
37e9297d28Sopenharmony_cisptr<VSyncReceiver> g_receiver = nullptr;
38e9297d28Sopenharmony_ci}
39e9297d28Sopenharmony_ci
40e9297d28Sopenharmony_civoid HelloComposer::Run(const std::vector<std::string> &runArgs)
41e9297d28Sopenharmony_ci{
42e9297d28Sopenharmony_ci    auto generator = CreateVSyncGenerator();
43e9297d28Sopenharmony_ci    sptr<VSyncController> vsyncController = new VSyncController(generator, 0);
44e9297d28Sopenharmony_ci    sptr<VSyncDistributor> vsyncDistributor = new VSyncDistributor(vsyncController, "HelloComposer");
45e9297d28Sopenharmony_ci    sptr<VSyncConnection> vsyncConnection = new VSyncConnection(vsyncDistributor, "HelloComposer");
46e9297d28Sopenharmony_ci    vsyncDistributor->AddConnection(vsyncConnection);
47e9297d28Sopenharmony_ci
48e9297d28Sopenharmony_ci    LOGI("start to run hello composer");
49e9297d28Sopenharmony_ci    backend_ = OHOS::Rosen::HdiBackend::GetInstance();
50e9297d28Sopenharmony_ci    if (backend_ == nullptr) {
51e9297d28Sopenharmony_ci        LOGE("HdiBackend::GetInstance fail");
52e9297d28Sopenharmony_ci        return;
53e9297d28Sopenharmony_ci    }
54e9297d28Sopenharmony_ci
55e9297d28Sopenharmony_ci    backend_->RegScreenHotplug(HelloComposer::OnScreenPlug, this);
56e9297d28Sopenharmony_ci    while (1) {
57e9297d28Sopenharmony_ci        if (!outputMap_.empty()) {
58e9297d28Sopenharmony_ci            break;
59e9297d28Sopenharmony_ci        }
60e9297d28Sopenharmony_ci    }
61e9297d28Sopenharmony_ci
62e9297d28Sopenharmony_ci    if (!initDeviceFinished_) {
63e9297d28Sopenharmony_ci        if (deviceConnected_) {
64e9297d28Sopenharmony_ci            CreateLayers();
65e9297d28Sopenharmony_ci        }
66e9297d28Sopenharmony_ci        initDeviceFinished_ = true;
67e9297d28Sopenharmony_ci    }
68e9297d28Sopenharmony_ci    LOGI("Init screen succeed");
69e9297d28Sopenharmony_ci
70e9297d28Sopenharmony_ci    backend_->RegPrepareComplete(HelloComposer::OnPrepareCompleted, this);
71e9297d28Sopenharmony_ci
72e9297d28Sopenharmony_ci    ParseArgs(runArgs);
73e9297d28Sopenharmony_ci
74e9297d28Sopenharmony_ci    sleep(1);
75e9297d28Sopenharmony_ci    std::shared_ptr<OHOS::AppExecFwk::EventRunner> runner = OHOS::AppExecFwk::EventRunner::Create(false);
76e9297d28Sopenharmony_ci    mainThreadHandler_ = std::make_shared<OHOS::AppExecFwk::EventHandler>(runner);
77e9297d28Sopenharmony_ci    g_receiver = new VSyncReceiver(vsyncConnection, nullptr, mainThreadHandler_);
78e9297d28Sopenharmony_ci    g_receiver->Init();
79e9297d28Sopenharmony_ci    mainThreadHandler_->PostTask([this] { this->RequestSync(); });
80e9297d28Sopenharmony_ci    runner->Run();
81e9297d28Sopenharmony_ci}
82e9297d28Sopenharmony_ci
83e9297d28Sopenharmony_civoid HelloComposer::ParseArgs(const std::vector<std::string> &runArgs)
84e9297d28Sopenharmony_ci{
85e9297d28Sopenharmony_ci    for (const std::string &arg : runArgs) {
86e9297d28Sopenharmony_ci        if (arg == "--dump") {
87e9297d28Sopenharmony_ci            dump_ = true;
88e9297d28Sopenharmony_ci        } else if (arg == "--testClient") {
89e9297d28Sopenharmony_ci            testClient_ = true;
90e9297d28Sopenharmony_ci        } else if (arg == "--testLayerRotate") {
91e9297d28Sopenharmony_ci            testLayerRotate_ = true;
92e9297d28Sopenharmony_ci        } else if (arg == "--YUV") {
93e9297d28Sopenharmony_ci            yuvFormat_ = true;
94e9297d28Sopenharmony_ci        } else if (arg == "--testLayerColor") {
95e9297d28Sopenharmony_ci            testLayerColor_ = true;
96e9297d28Sopenharmony_ci        }
97e9297d28Sopenharmony_ci    }
98e9297d28Sopenharmony_ci}
99e9297d28Sopenharmony_ci
100e9297d28Sopenharmony_civoid HelloComposer::OnScreenPlug(std::shared_ptr<HdiOutput> &output, bool connected, void* data)
101e9297d28Sopenharmony_ci{
102e9297d28Sopenharmony_ci    LOGI("enter OnScreenPlug, connected is %{public}d", connected);
103e9297d28Sopenharmony_ci    auto* thisPtr = static_cast<HelloComposer *>(data);
104e9297d28Sopenharmony_ci    thisPtr->OnHotPlugEvent(output, connected);
105e9297d28Sopenharmony_ci}
106e9297d28Sopenharmony_ci
107e9297d28Sopenharmony_civoid HelloComposer::OnPrepareCompleted(
108e9297d28Sopenharmony_ci    sptr<Surface> &surface, const struct PrepareCompleteParam &param, void* data)
109e9297d28Sopenharmony_ci{
110e9297d28Sopenharmony_ci    if (!param.needFlushFramebuffer) {
111e9297d28Sopenharmony_ci        return;
112e9297d28Sopenharmony_ci    }
113e9297d28Sopenharmony_ci
114e9297d28Sopenharmony_ci    if (surface == nullptr) {
115e9297d28Sopenharmony_ci        LOGE("surface is null");
116e9297d28Sopenharmony_ci        return;
117e9297d28Sopenharmony_ci    }
118e9297d28Sopenharmony_ci
119e9297d28Sopenharmony_ci    if (data == nullptr) {
120e9297d28Sopenharmony_ci        LOGE("data ptr is null");
121e9297d28Sopenharmony_ci        return;
122e9297d28Sopenharmony_ci    }
123e9297d28Sopenharmony_ci
124e9297d28Sopenharmony_ci    auto* thisPtr = static_cast<HelloComposer *>(data);
125e9297d28Sopenharmony_ci    thisPtr->DoPrepareCompleted(surface, param);
126e9297d28Sopenharmony_ci}
127e9297d28Sopenharmony_ci
128e9297d28Sopenharmony_civoid HelloComposer::CreateLayers()
129e9297d28Sopenharmony_ci{
130e9297d28Sopenharmony_ci    for (auto iter = outputMap_.begin(); iter != outputMap_.end(); ++iter) {
131e9297d28Sopenharmony_ci        currScreenId_ = iter->first;
132e9297d28Sopenharmony_ci        CreateShowLayers();
133e9297d28Sopenharmony_ci    }
134e9297d28Sopenharmony_ci}
135e9297d28Sopenharmony_ci
136e9297d28Sopenharmony_civoid HelloComposer::CreateShowLayers()
137e9297d28Sopenharmony_ci{
138e9297d28Sopenharmony_ci    if (screensMap_.count(currScreenId_) != 0) {
139e9297d28Sopenharmony_ci        LOGI("Screen[%{public}d] has already created", currScreenId_);
140e9297d28Sopenharmony_ci        return;
141e9297d28Sopenharmony_ci    }
142e9297d28Sopenharmony_ci
143e9297d28Sopenharmony_ci    uint32_t screenId = CreatePhysicalScreen();
144e9297d28Sopenharmony_ci
145e9297d28Sopenharmony_ci    LOGI("Create screen[%{public}d], and created a total of %{public}zu screens", screenId, screensMap_.size());
146e9297d28Sopenharmony_ci
147e9297d28Sopenharmony_ci    InitLayers(screenId);
148e9297d28Sopenharmony_ci}
149e9297d28Sopenharmony_ci
150e9297d28Sopenharmony_civoid HelloComposer::RequestSync()
151e9297d28Sopenharmony_ci{
152e9297d28Sopenharmony_ci    Sync(0, nullptr);
153e9297d28Sopenharmony_ci}
154e9297d28Sopenharmony_ci
155e9297d28Sopenharmony_civoid HelloComposer::InitLayers(uint32_t screenId)
156e9297d28Sopenharmony_ci{
157e9297d28Sopenharmony_ci    LOGI("Init layers, screenId is %{public}d", screenId);
158e9297d28Sopenharmony_ci    uint32_t displayWidth = displayWidthsMap_[screenId];
159e9297d28Sopenharmony_ci    uint32_t displayHeight = displayHeightsMap_[screenId];
160e9297d28Sopenharmony_ci
161e9297d28Sopenharmony_ci    std::vector<std::unique_ptr<LayerContext>> &drawLayers = drawLayersMap_[screenId];
162e9297d28Sopenharmony_ci
163e9297d28Sopenharmony_ci    uint32_t statusHeight = displayHeight / 10; // statusHeight is 1 / 10 displayHeight
164e9297d28Sopenharmony_ci    uint32_t launcherHeight = displayHeight - statusHeight * 2; // index 1, cal launcher height 2
165e9297d28Sopenharmony_ci    uint32_t navigationY = displayHeight - statusHeight;
166e9297d28Sopenharmony_ci    LOGI("displayWidth[%{public}d], displayHeight[%{public}d], statusHeight[%{public}d], "
167e9297d28Sopenharmony_ci         "launcherHeight[%{public}d], navigationY[%{public}d]", displayWidth, displayHeight,
168e9297d28Sopenharmony_ci         statusHeight, launcherHeight, navigationY);
169e9297d28Sopenharmony_ci
170e9297d28Sopenharmony_ci    // status bar
171e9297d28Sopenharmony_ci    drawLayers.emplace_back(std::make_unique<LayerContext>(
172e9297d28Sopenharmony_ci        GraphicIRect { 0, 0, displayWidth, statusHeight },
173e9297d28Sopenharmony_ci        GraphicIRect { 0, 0, displayWidth, statusHeight },
174e9297d28Sopenharmony_ci        1, LayerType::LAYER_STATUS));
175e9297d28Sopenharmony_ci
176e9297d28Sopenharmony_ci    // launcher
177e9297d28Sopenharmony_ci    drawLayers.emplace_back(std::make_unique<LayerContext>(
178e9297d28Sopenharmony_ci        GraphicIRect { 0, statusHeight, displayWidth, launcherHeight },
179e9297d28Sopenharmony_ci        GraphicIRect { 0, 0, displayWidth, launcherHeight },
180e9297d28Sopenharmony_ci        0, LayerType::LAYER_LAUNCHER));
181e9297d28Sopenharmony_ci
182e9297d28Sopenharmony_ci    // navigation bar
183e9297d28Sopenharmony_ci    drawLayers.emplace_back(std::make_unique<LayerContext>(
184e9297d28Sopenharmony_ci        GraphicIRect { 0, navigationY, displayWidth, statusHeight },
185e9297d28Sopenharmony_ci        GraphicIRect { 0, 0, displayWidth, statusHeight },
186e9297d28Sopenharmony_ci        1, LayerType::LAYER_NAVIGATION));
187e9297d28Sopenharmony_ci
188e9297d28Sopenharmony_ci    uint32_t layerWidth = displayWidth / 4; // layer width is 1/4 displayWidth
189e9297d28Sopenharmony_ci    uint32_t layerHeight = displayHeight / 4; // layer height is 1/4 of displayHeight
190e9297d28Sopenharmony_ci    uint32_t layerPositionX = displayWidth / 2 - layerWidth / 2; // x is (displayWidth - layerWidth) / 2
191e9297d28Sopenharmony_ci    uint32_t layerPositionY = displayHeight / 2 - layerHeight / 2; // y is (displayHeight - layerHeight) / 2
192e9297d28Sopenharmony_ci    LOGI("Layer position is: [x, y, w, h: [%{public}d, %{public}d, %{public}d, %{public}d]]",
193e9297d28Sopenharmony_ci          layerPositionX, layerPositionY, layerWidth, layerHeight);
194e9297d28Sopenharmony_ci
195e9297d28Sopenharmony_ci    // extra layer 1
196e9297d28Sopenharmony_ci    drawLayers.emplace_back(std::make_unique<LayerContext>(
197e9297d28Sopenharmony_ci        GraphicIRect { layerPositionX, layerPositionY, layerWidth, layerHeight },
198e9297d28Sopenharmony_ci        GraphicIRect { 0, 0, layerWidth, layerHeight },
199e9297d28Sopenharmony_ci        1, LayerType::LAYER_EXTRA)); // 2 is zorder
200e9297d28Sopenharmony_ci}
201e9297d28Sopenharmony_ci
202e9297d28Sopenharmony_civoid HelloComposer::Sync(int64_t, void *data)
203e9297d28Sopenharmony_ci{
204e9297d28Sopenharmony_ci    VSyncReceiver::FrameCallback fcb = {
205e9297d28Sopenharmony_ci        .userData_ = data,
206e9297d28Sopenharmony_ci        .callback_ = [this] { this->Sync(::std::placeholders::_1, ::std::placeholders::_2); },
207e9297d28Sopenharmony_ci    };
208e9297d28Sopenharmony_ci
209e9297d28Sopenharmony_ci    if (g_receiver != nullptr) {
210e9297d28Sopenharmony_ci        g_receiver->RequestNextVSync(fcb);
211e9297d28Sopenharmony_ci    }
212e9297d28Sopenharmony_ci
213e9297d28Sopenharmony_ci    if (!ready_) {
214e9297d28Sopenharmony_ci        LOGE("hdi screen is not ready");
215e9297d28Sopenharmony_ci        return;
216e9297d28Sopenharmony_ci    }
217e9297d28Sopenharmony_ci
218e9297d28Sopenharmony_ci    Draw();
219e9297d28Sopenharmony_ci}
220e9297d28Sopenharmony_ci
221e9297d28Sopenharmony_civoid HelloComposer::SetRunArgs(const std::unique_ptr<LayerContext> &drawLayer) const
222e9297d28Sopenharmony_ci{
223e9297d28Sopenharmony_ci    LayerType type = drawLayer->GetLayerType();
224e9297d28Sopenharmony_ci    if (testLayerColor_) {
225e9297d28Sopenharmony_ci        drawLayer->SetTestLayerColor(true);
226e9297d28Sopenharmony_ci    }
227e9297d28Sopenharmony_ci
228e9297d28Sopenharmony_ci    if (type < LayerType::LAYER_EXTRA) {
229e9297d28Sopenharmony_ci        return;
230e9297d28Sopenharmony_ci    }
231e9297d28Sopenharmony_ci
232e9297d28Sopenharmony_ci    if (testClient_) {
233e9297d28Sopenharmony_ci        drawLayer->SetTestClientStatus(true);
234e9297d28Sopenharmony_ci    }
235e9297d28Sopenharmony_ci
236e9297d28Sopenharmony_ci    if (testLayerRotate_) {
237e9297d28Sopenharmony_ci        drawLayer->SetTestRotateStatus(true);
238e9297d28Sopenharmony_ci    }
239e9297d28Sopenharmony_ci
240e9297d28Sopenharmony_ci    if (yuvFormat_) {
241e9297d28Sopenharmony_ci        drawLayer->SetTestYUVStatus(true);
242e9297d28Sopenharmony_ci    }
243e9297d28Sopenharmony_ci}
244e9297d28Sopenharmony_ci
245e9297d28Sopenharmony_civoid HelloComposer::Draw()
246e9297d28Sopenharmony_ci{
247e9297d28Sopenharmony_ci    for (auto iter = drawLayersMap_.begin(); iter != drawLayersMap_.end(); ++iter) {
248e9297d28Sopenharmony_ci        uint32_t screenId = iter->first;
249e9297d28Sopenharmony_ci        std::vector<std::unique_ptr<LayerContext>> &drawLayers = drawLayersMap_[screenId];
250e9297d28Sopenharmony_ci        std::vector<LayerInfoPtr> layerVec;
251e9297d28Sopenharmony_ci        for (auto &drawLayer : drawLayers) { // producer
252e9297d28Sopenharmony_ci            SetRunArgs(drawLayer);
253e9297d28Sopenharmony_ci            drawLayer->DrawBufferColor();
254e9297d28Sopenharmony_ci        }
255e9297d28Sopenharmony_ci
256e9297d28Sopenharmony_ci        for (auto &drawLayer : drawLayers) { // consumer
257e9297d28Sopenharmony_ci            drawLayer->FillHDIBuffer();
258e9297d28Sopenharmony_ci            drawLayer->FillHDILayer();
259e9297d28Sopenharmony_ci            layerVec.emplace_back(drawLayer->GetHdiLayer());
260e9297d28Sopenharmony_ci        }
261e9297d28Sopenharmony_ci
262e9297d28Sopenharmony_ci        curOutput_ = outputMap_[screenId];
263e9297d28Sopenharmony_ci        curOutput_->SetLayerInfo(layerVec);
264e9297d28Sopenharmony_ci
265e9297d28Sopenharmony_ci        GraphicIRect damageRect;
266e9297d28Sopenharmony_ci        damageRect.x = 0;
267e9297d28Sopenharmony_ci        damageRect.y = 0;
268e9297d28Sopenharmony_ci        damageRect.w = static_cast<int32_t>(displayWidthsMap_[screenId]);
269e9297d28Sopenharmony_ci        damageRect.h = static_cast<int32_t>(displayHeightsMap_[screenId]);
270e9297d28Sopenharmony_ci        std::vector<GraphicIRect> outputDamages;
271e9297d28Sopenharmony_ci        outputDamages.emplace_back(damageRect);
272e9297d28Sopenharmony_ci        curOutput_->SetOutputDamages(outputDamages);
273e9297d28Sopenharmony_ci
274e9297d28Sopenharmony_ci        if (dump_) {
275e9297d28Sopenharmony_ci            std::string result;
276e9297d28Sopenharmony_ci            curOutput_->Dump(result);
277e9297d28Sopenharmony_ci            LOGI("Dump layer result after ReleaseBuffer : %{public}s", result.c_str());
278e9297d28Sopenharmony_ci        }
279e9297d28Sopenharmony_ci
280e9297d28Sopenharmony_ci        backend_->Repaint(curOutput_);
281e9297d28Sopenharmony_ci        auto layersReleaseFence = curOutput_->GetLayersReleaseFence();
282e9297d28Sopenharmony_ci        for (auto& layerContext : drawLayers) {
283e9297d28Sopenharmony_ci            auto preBuffer = layerContext->GetPreBuffer();
284e9297d28Sopenharmony_ci            int32_t releaseFence = -1;
285e9297d28Sopenharmony_ci            sptr<SyncFence> tempFence = new SyncFence(releaseFence);
286e9297d28Sopenharmony_ci            layerContext->GetHdiLayer()->GetSurface()->ReleaseBuffer(preBuffer, tempFence);
287e9297d28Sopenharmony_ci            tempFence->Wait(100); // 100 ms
288e9297d28Sopenharmony_ci        }
289e9297d28Sopenharmony_ci    }
290e9297d28Sopenharmony_ci}
291e9297d28Sopenharmony_ci
292e9297d28Sopenharmony_ciuint32_t HelloComposer::CreatePhysicalScreen()
293e9297d28Sopenharmony_ci{
294e9297d28Sopenharmony_ci    std::vector<GraphicDisplayModeInfo> displayModeInfos;
295e9297d28Sopenharmony_ci    uint32_t screenId = currScreenId_;
296e9297d28Sopenharmony_ci    std::unique_ptr<HdiScreen> screen = HdiScreen::CreateHdiScreen(screenId);
297e9297d28Sopenharmony_ci    screen->Init();
298e9297d28Sopenharmony_ci    screen->GetScreenSupportedModes(displayModeInfos);
299e9297d28Sopenharmony_ci    size_t supportModeNum = displayModeInfos.size();
300e9297d28Sopenharmony_ci    if (supportModeNum > 0) {
301e9297d28Sopenharmony_ci        uint32_t currentModeIndex = 0;
302e9297d28Sopenharmony_ci        screen->GetScreenMode(currentModeIndex);
303e9297d28Sopenharmony_ci        LOGI("currentModeIndex:%{public}d", currentModeIndex);
304e9297d28Sopenharmony_ci        for (size_t i = 0; i < supportModeNum; i++) {
305e9297d28Sopenharmony_ci            LOGI("modes(%{public}d) %{public}dx%{public}d freq:%{public}d",
306e9297d28Sopenharmony_ci                displayModeInfos[i].id, displayModeInfos[i].width,
307e9297d28Sopenharmony_ci                displayModeInfos[i].height, displayModeInfos[i].freshRate);
308e9297d28Sopenharmony_ci            if (displayModeInfos[i].id == static_cast<int32_t>(currentModeIndex)) {
309e9297d28Sopenharmony_ci                freq_ = 30; // 30 freq
310e9297d28Sopenharmony_ci                displayWidthsMap_[screenId] = static_cast<uint32_t>(displayModeInfos[i].width);
311e9297d28Sopenharmony_ci                displayHeightsMap_[screenId] = static_cast<uint32_t>(displayModeInfos[i].height);
312e9297d28Sopenharmony_ci                break;
313e9297d28Sopenharmony_ci            }
314e9297d28Sopenharmony_ci        }
315e9297d28Sopenharmony_ci        screen->SetScreenPowerStatus(GraphicDispPowerStatus::GRAPHIC_POWER_STATUS_ON);
316e9297d28Sopenharmony_ci        screen->SetScreenMode(currentModeIndex);
317e9297d28Sopenharmony_ci        LOGI("SetScreenMode: currentModeIndex(%{public}d)", currentModeIndex);
318e9297d28Sopenharmony_ci
319e9297d28Sopenharmony_ci        GraphicDispPowerStatus powerState;
320e9297d28Sopenharmony_ci        screen->GetScreenPowerStatus(powerState);
321e9297d28Sopenharmony_ci        LOGI("get poweState:%{public}d", powerState);
322e9297d28Sopenharmony_ci    }
323e9297d28Sopenharmony_ci
324e9297d28Sopenharmony_ci    GraphicDisplayCapability info;
325e9297d28Sopenharmony_ci    screen->GetScreenCapability(info);
326e9297d28Sopenharmony_ci    LOGI("ScreenCapability: name(%{public}s), type(%{public}d), phyWidth(%{public}d), "
327e9297d28Sopenharmony_ci         "phyHeight(%{public}d)", info.name.c_str(), info.type, info.phyWidth, info.phyHeight);
328e9297d28Sopenharmony_ci    LOGI("ScreenCapability: supportLayers(%{public}d), virtualDispCount(%{public}d), "
329e9297d28Sopenharmony_ci         "supportWriteBack(%{public}d), propertyCount(%{public}d)", info.supportLayers,
330e9297d28Sopenharmony_ci         info.virtualDispCount, info.supportWriteBack, info.propertyCount);
331e9297d28Sopenharmony_ci
332e9297d28Sopenharmony_ci    ready_ = true;
333e9297d28Sopenharmony_ci
334e9297d28Sopenharmony_ci    screensMap_[screenId] = std::move(screen);
335e9297d28Sopenharmony_ci
336e9297d28Sopenharmony_ci    LOGI("CreatePhysicalScreen, screenId is %{public}d", screenId);
337e9297d28Sopenharmony_ci
338e9297d28Sopenharmony_ci    return screenId;
339e9297d28Sopenharmony_ci}
340e9297d28Sopenharmony_ci
341e9297d28Sopenharmony_civoid HelloComposer::OnHotPlugEvent(std::shared_ptr<HdiOutput> &output, bool connected)
342e9297d28Sopenharmony_ci{
343e9297d28Sopenharmony_ci    if (mainThreadHandler_ == nullptr) {
344e9297d28Sopenharmony_ci        LOGI("In main thread, call OnHotPlug directly");
345e9297d28Sopenharmony_ci        OnHotPlug(output, connected);
346e9297d28Sopenharmony_ci    } else {
347e9297d28Sopenharmony_ci        LOGI("In sub thread, post msg to main thread");
348e9297d28Sopenharmony_ci        mainThreadHandler_->PostTask([this] { this->OnHotPlug(output, connected); });
349e9297d28Sopenharmony_ci    }
350e9297d28Sopenharmony_ci}
351e9297d28Sopenharmony_ci
352e9297d28Sopenharmony_civoid HelloComposer::OnHotPlug(std::shared_ptr<HdiOutput> &output, bool connected)
353e9297d28Sopenharmony_ci{
354e9297d28Sopenharmony_ci    /*
355e9297d28Sopenharmony_ci     * Currently, IPC communication cannot be nested. Therefore, Vblank registration can be
356e9297d28Sopenharmony_ci     * initiated only after the initialization of the device is complete.
357e9297d28Sopenharmony_ci     */
358e9297d28Sopenharmony_ci    currScreenId_ = output->GetScreenId();
359e9297d28Sopenharmony_ci    outputMap_[currScreenId_] = output;
360e9297d28Sopenharmony_ci    deviceConnected_ = connected;
361e9297d28Sopenharmony_ci
362e9297d28Sopenharmony_ci    if (!connected) {
363e9297d28Sopenharmony_ci        RemoveOffScreenData(currScreenId_);
364e9297d28Sopenharmony_ci    }
365e9297d28Sopenharmony_ci
366e9297d28Sopenharmony_ci    if (!initDeviceFinished_) {
367e9297d28Sopenharmony_ci        LOGI("Init the device has not finished yet");
368e9297d28Sopenharmony_ci        return;
369e9297d28Sopenharmony_ci    }
370e9297d28Sopenharmony_ci
371e9297d28Sopenharmony_ci    LOGI("Callback HotPlugEvent, screenId is %{public}d, connected is %{public}u", currScreenId_, connected);
372e9297d28Sopenharmony_ci
373e9297d28Sopenharmony_ci    if (connected) {
374e9297d28Sopenharmony_ci        CreateShowLayers();
375e9297d28Sopenharmony_ci    }
376e9297d28Sopenharmony_ci}
377e9297d28Sopenharmony_ci
378e9297d28Sopenharmony_civoid HelloComposer::RemoveOffScreenData(uint32_t offScreenId)
379e9297d28Sopenharmony_ci{
380e9297d28Sopenharmony_ci    LOGI("Screen[%{public}d] is unplugged, and remove data", offScreenId);
381e9297d28Sopenharmony_ci
382e9297d28Sopenharmony_ci    auto widthIter = displayWidthsMap_.begin();
383e9297d28Sopenharmony_ci    while (widthIter != displayWidthsMap_.end()) {
384e9297d28Sopenharmony_ci        uint32_t screenId = widthIter->first;
385e9297d28Sopenharmony_ci        if (screenId == offScreenId) {
386e9297d28Sopenharmony_ci            displayWidthsMap_.erase(widthIter++);
387e9297d28Sopenharmony_ci        } else {
388e9297d28Sopenharmony_ci            ++widthIter;
389e9297d28Sopenharmony_ci        }
390e9297d28Sopenharmony_ci    }
391e9297d28Sopenharmony_ci
392e9297d28Sopenharmony_ci    auto heightIter = displayHeightsMap_.begin();
393e9297d28Sopenharmony_ci    while (heightIter != displayHeightsMap_.end()) {
394e9297d28Sopenharmony_ci        uint32_t screenId = heightIter->first;
395e9297d28Sopenharmony_ci        if (screenId == offScreenId) {
396e9297d28Sopenharmony_ci            displayHeightsMap_.erase(heightIter++);
397e9297d28Sopenharmony_ci        } else {
398e9297d28Sopenharmony_ci            ++heightIter;
399e9297d28Sopenharmony_ci        }
400e9297d28Sopenharmony_ci    }
401e9297d28Sopenharmony_ci
402e9297d28Sopenharmony_ci    auto outputIter = outputMap_.begin();
403e9297d28Sopenharmony_ci    while (outputIter != outputMap_.end()) {
404e9297d28Sopenharmony_ci        uint32_t screenId = outputIter->first;
405e9297d28Sopenharmony_ci        if (screenId == offScreenId) {
406e9297d28Sopenharmony_ci            outputMap_.erase(outputIter++);
407e9297d28Sopenharmony_ci        } else {
408e9297d28Sopenharmony_ci            ++outputIter;
409e9297d28Sopenharmony_ci        }
410e9297d28Sopenharmony_ci    }
411e9297d28Sopenharmony_ci
412e9297d28Sopenharmony_ci    auto screenIter = screensMap_.begin();
413e9297d28Sopenharmony_ci    while (screenIter != screensMap_.end()) {
414e9297d28Sopenharmony_ci        uint32_t screenId = screenIter->first;
415e9297d28Sopenharmony_ci        if (screenId == offScreenId) {
416e9297d28Sopenharmony_ci            screensMap_.erase(screenIter++);
417e9297d28Sopenharmony_ci        } else {
418e9297d28Sopenharmony_ci            ++screenIter;
419e9297d28Sopenharmony_ci        }
420e9297d28Sopenharmony_ci    }
421e9297d28Sopenharmony_ci
422e9297d28Sopenharmony_ci    auto layerIter = drawLayersMap_.begin();
423e9297d28Sopenharmony_ci    while (layerIter != drawLayersMap_.end()) {
424e9297d28Sopenharmony_ci        uint32_t screenId = layerIter->first;
425e9297d28Sopenharmony_ci        if (screenId == offScreenId) {
426e9297d28Sopenharmony_ci            drawLayersMap_.erase(layerIter++);
427e9297d28Sopenharmony_ci        } else {
428e9297d28Sopenharmony_ci            ++layerIter;
429e9297d28Sopenharmony_ci        }
430e9297d28Sopenharmony_ci    }
431e9297d28Sopenharmony_ci}
432e9297d28Sopenharmony_ci
433e9297d28Sopenharmony_cinamespace {
434e9297d28Sopenharmony_civoid DrawFrameBufferData(void *image, uint32_t width, uint32_t height)
435e9297d28Sopenharmony_ci{
436e9297d28Sopenharmony_ci    static uint32_t value = 0x00;
437e9297d28Sopenharmony_ci    value++;
438e9297d28Sopenharmony_ci
439e9297d28Sopenharmony_ci    uint32_t *pixel = static_cast<uint32_t *>(image);
440e9297d28Sopenharmony_ci    for (uint32_t x = 0; x < width; x++) {
441e9297d28Sopenharmony_ci        for (uint32_t y = 0;  y < height; y++) {
442e9297d28Sopenharmony_ci            *pixel++ = value;
443e9297d28Sopenharmony_ci        }
444e9297d28Sopenharmony_ci    }
445e9297d28Sopenharmony_ci}
446e9297d28Sopenharmony_ci}
447e9297d28Sopenharmony_ci
448e9297d28Sopenharmony_civoid HelloComposer::DoPrepareCompleted(sptr<Surface> surface, const struct PrepareCompleteParam &param)
449e9297d28Sopenharmony_ci{
450e9297d28Sopenharmony_ci    uint32_t screenId = curOutput_->GetScreenId();
451e9297d28Sopenharmony_ci    uint32_t displayWidth = displayWidthsMap_[screenId];
452e9297d28Sopenharmony_ci    uint32_t displayHeight = displayHeightsMap_[screenId];
453e9297d28Sopenharmony_ci
454e9297d28Sopenharmony_ci    BufferRequestConfig requestConfig = {
455e9297d28Sopenharmony_ci        .width = displayWidth,  // need display width
456e9297d28Sopenharmony_ci        .height = displayHeight, // need display height
457e9297d28Sopenharmony_ci        .strideAlignment = 0x8,
458e9297d28Sopenharmony_ci        .format = GRAPHIC_PIXEL_FMT_BGRA_8888,
459e9297d28Sopenharmony_ci        .usage = BUFFER_USAGE_CPU_READ | BUFFER_USAGE_CPU_WRITE | BUFFER_USAGE_MEM_DMA,
460e9297d28Sopenharmony_ci        .timeout = 0,
461e9297d28Sopenharmony_ci    };
462e9297d28Sopenharmony_ci
463e9297d28Sopenharmony_ci    int32_t releaseFence = -1;
464e9297d28Sopenharmony_ci    sptr<SurfaceBuffer> fbBuffer = nullptr;
465e9297d28Sopenharmony_ci    SurfaceError ret = surface->RequestBuffer(fbBuffer, releaseFence, requestConfig);
466e9297d28Sopenharmony_ci    if (ret != 0) {
467e9297d28Sopenharmony_ci        LOGE("RequestBuffer failed: %{public}s", SurfaceErrorStr(ret).c_str());
468e9297d28Sopenharmony_ci        return;
469e9297d28Sopenharmony_ci    }
470e9297d28Sopenharmony_ci
471e9297d28Sopenharmony_ci    sptr<SyncFence> tempFence = new SyncFence(releaseFence);
472e9297d28Sopenharmony_ci    tempFence->Wait(100); // 100 ms
473e9297d28Sopenharmony_ci
474e9297d28Sopenharmony_ci    bool hasClient = false;
475e9297d28Sopenharmony_ci    const std::vector<LayerInfoPtr> &layers = param.layers;
476e9297d28Sopenharmony_ci    for (const LayerInfoPtr &layer : layers) {
477e9297d28Sopenharmony_ci        if (layer->GetCompositionType() == GraphicCompositionType::GRAPHIC_COMPOSITION_CLIENT) {
478e9297d28Sopenharmony_ci            hasClient = true;
479e9297d28Sopenharmony_ci        }
480e9297d28Sopenharmony_ci    }
481e9297d28Sopenharmony_ci
482e9297d28Sopenharmony_ci    auto addr = static_cast<uint8_t *>(fbBuffer->GetVirAddr());
483e9297d28Sopenharmony_ci    if (hasClient) {
484e9297d28Sopenharmony_ci        DrawFrameBufferData(addr, static_cast<uint32_t>(fbBuffer->GetWidth()),
485e9297d28Sopenharmony_ci            static_cast<uint32_t>(fbBuffer->GetHeight()));
486e9297d28Sopenharmony_ci    } else {
487e9297d28Sopenharmony_ci        int32_t memsetRet = memset_s(addr, fbBuffer->GetSize(), 0, fbBuffer->GetSize());
488e9297d28Sopenharmony_ci        if (memsetRet != 0) {
489e9297d28Sopenharmony_ci            LOGE("memset_s failed");
490e9297d28Sopenharmony_ci        }
491e9297d28Sopenharmony_ci    }
492e9297d28Sopenharmony_ci
493e9297d28Sopenharmony_ci    BufferFlushConfig flushConfig = {
494e9297d28Sopenharmony_ci        .damage = {
495e9297d28Sopenharmony_ci            .w = displayWidth,
496e9297d28Sopenharmony_ci            .h = displayHeight,
497e9297d28Sopenharmony_ci        }
498e9297d28Sopenharmony_ci    };
499e9297d28Sopenharmony_ci
500e9297d28Sopenharmony_ci    /*
501e9297d28Sopenharmony_ci     * if use GPU produce data, flush with gpu fence
502e9297d28Sopenharmony_ci     */
503e9297d28Sopenharmony_ci    ret = surface->FlushBuffer(fbBuffer, -1, flushConfig);
504e9297d28Sopenharmony_ci    if (ret != 0) {
505e9297d28Sopenharmony_ci        LOGE("FlushBuffer failed: %{public}s", SurfaceErrorStr(ret).c_str());
506e9297d28Sopenharmony_ci    }
507e9297d28Sopenharmony_ci}
508