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 ¶m, 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 ¶m) 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