1 /*
2 * Copyright (c) 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 #include "boot_picture_player.h"
16
17 #include "event_handler.h"
18 #include "log.h"
19 #include "rs_trace.h"
20 #include "transaction/rs_interfaces.h"
21
22 namespace OHOS {
23 namespace {
24 const std::string BOOT_PIC_ZIP = "/system/etc/graphic/bootpic.zip";
25 }
26
BootPicturePlayer(const PlayerParams & params)27 BootPicturePlayer::BootPicturePlayer(const PlayerParams& params)
28 {
29 resPath_ = params.resPath;
30 rsSurface_ = params.rsSurface;
31 InitPicCoordinates(params.screenId);
32 }
33
Play()34 void BootPicturePlayer::Play()
35 {
36 auto& rsClient = OHOS::Rosen::RSInterfaces::GetInstance();
37 while (receiver_ == nullptr) {
38 LOGI("receiver is nullptr, try create again");
39 receiver_ = rsClient.CreateVSyncReceiver("BootAnimation", AppExecFwk::EventHandler::Current());
40 }
41
42 VsyncError ret = receiver_->Init();
43 if (ret) {
44 LOGE("vsync receiver init failed: %{public}d", ret);
45 AppExecFwk::EventRunner::Current()->Stop();
46 return;
47 }
48
49 ROSEN_TRACE_BEGIN(HITRACE_TAG_GRAPHIC_AGP, "BootAnimation::preload");
50 if (ReadPicZipFile(imageVector_, freq_)) {
51 imgVecSize_ = static_cast<int32_t> (imageVector_.size());
52 } else {
53 LOGE("read pic zip failed");
54 AppExecFwk::EventRunner::Current()->Stop();
55 return;
56 }
57 ROSEN_TRACE_END(HITRACE_TAG_GRAPHIC_AGP);
58
59 OHOS::Rosen::VSyncReceiver::FrameCallback fcb = {
60 .userData_ = this,
61 .callback_ = [this](int64_t, void*) { this->OnVsync(); },
62 };
63 int32_t changeFreq = static_cast<int32_t> (1000.0 / freq_ / 16);
64 ret = receiver_->SetVSyncRate(fcb, changeFreq);
65 if (ret) {
66 LOGE("SetVSyncRate failed: %{public}d %{public}d", ret, freq_);
67 AppExecFwk::EventRunner::Current()->Stop();
68 return;
69 } else {
70 LOGI("SetVSyncRate success: %{public}d, %{public}d", freq_, changeFreq);
71 }
72 }
73
InitPicCoordinates(Rosen::ScreenId screenId)74 void BootPicturePlayer::InitPicCoordinates(Rosen::ScreenId screenId)
75 {
76 Rosen::RSInterfaces& interface = Rosen::RSInterfaces::GetInstance();
77 Rosen::RSScreenModeInfo modeinfo = interface.GetScreenActiveMode(screenId);
78 windowWidth_ = modeinfo.GetScreenWidth();
79 windowHeight_ = modeinfo.GetScreenHeight();
80 if (windowWidth_ >= windowHeight_) {
81 realHeight_ = windowHeight_;
82 realWidth_ = realHeight_;
83 pointX_ = (windowWidth_ - realWidth_) / NUMBER_TWO;
84 } else {
85 realWidth_ = windowWidth_;
86 realHeight_ = realWidth_;
87 pointY_ = (windowHeight_ - realHeight_) / NUMBER_TWO;
88 }
89 }
90
ReadPicZipFile(ImageStructVec & imgVec,int32_t & freq)91 bool BootPicturePlayer::ReadPicZipFile(ImageStructVec& imgVec, int32_t& freq)
92 {
93 FrameRateConfig frameConfig;
94 ReadZipFile(GetPicZipPath(), imgVec, frameConfig);
95 int32_t imageNum = static_cast<int32_t>(imgVec.size());
96 if (imageNum < 0) {
97 LOGE("zip pic num is invalid.");
98 return false;
99 }
100
101 SortZipFile(imgVec);
102
103 if (CheckFrameRateValid(frameConfig.frameRate)) {
104 freq = frameConfig.frameRate;
105 } else {
106 LOGW("Only Support 30, 60 frame rate: %{public}d", frameConfig.frameRate);
107 }
108 LOGI("read freq: %{public}d, pic num: %{public}d", freq, imageNum);
109 return true;
110 }
111
GetPicZipPath()112 std::string BootPicturePlayer::GetPicZipPath()
113 {
114 if (!IsFileExisted(resPath_)) {
115 LOGI("pic zip path empty or not exist, use default path");
116 return BOOT_PIC_ZIP;
117 }
118 return resPath_;
119 }
120
CheckFrameRateValid(int32_t frameRate)121 bool BootPicturePlayer::CheckFrameRateValid(int32_t frameRate)
122 {
123 std::vector<int> freqs = {60, 30};
124 int nCount = std::count(freqs.begin(), freqs.end(), frameRate);
125 return nCount > 0;
126 }
127
OnVsync()128 void BootPicturePlayer::OnVsync()
129 {
130 PostTask([this] { this->Draw(); });
131 }
132
Draw()133 bool BootPicturePlayer::Draw()
134 {
135 if (picCurNo_ >= (imgVecSize_ - 1)) {
136 LOGI("play sequence frames end");
137 AppExecFwk::EventRunner::Current()->Stop();
138 return false;
139 }
140 picCurNo_ = picCurNo_ + 1;
141 ROSEN_TRACE_BEGIN(HITRACE_TAG_GRAPHIC_AGP, "BootAnimation::Draw RequestFrame");
142 auto frame = rsSurface_->RequestFrame(windowWidth_, windowHeight_);
143 ROSEN_TRACE_END(HITRACE_TAG_GRAPHIC_AGP);
144 if (frame == nullptr) {
145 LOGE("draw frame is nullptr");
146 AppExecFwk::EventRunner::Current()->Stop();
147 return false;
148 }
149 #ifdef NEW_RENDER_CONTEXT
150 if (rsSurface_ == nullptr) {
151 LOGE("rsSurface is nullptr");
152 AppExecFwk::EventRunner::Current()->Stop();
153 return false;
154 }
155 auto canvas = rsSurface_->GetCanvas();
156 OnDraw(canvas, picCurNo_);
157 ROSEN_TRACE_BEGIN(HITRACE_TAG_GRAPHIC_AGP, "BootAnimation::Draw FlushFrame");
158 rsSurface_->FlushFrame();
159 ROSEN_TRACE_END(HITRACE_TAG_GRAPHIC_AGP);
160 #else
161 rsSurfaceFrame_ = std::move(frame);
162 auto canvas = rsSurfaceFrame_->GetCanvas();
163 OnDraw(canvas, picCurNo_);
164 ROSEN_TRACE_BEGIN(HITRACE_TAG_GRAPHIC_AGP, "BootAnimation::Draw FlushFrame");
165 rsSurface_->FlushFrame(rsSurfaceFrame_);
166 ROSEN_TRACE_END(HITRACE_TAG_GRAPHIC_AGP);
167 #endif
168 return true;
169 }
170
OnDraw(Rosen::Drawing::CoreCanvas * canvas,int32_t curNo)171 bool BootPicturePlayer::OnDraw(Rosen::Drawing::CoreCanvas* canvas, int32_t curNo)
172 {
173 if (canvas == nullptr) {
174 LOGE("OnDraw canvas is nullptr");
175 AppExecFwk::EventRunner::Current()->Stop();
176 return false;
177 }
178 if (curNo > (imgVecSize_ - 1) || curNo < 0) {
179 AppExecFwk::EventRunner::Current()->Stop();
180 return false;
181 }
182 std::shared_ptr<ImageStruct> imgstruct = imageVector_[curNo];
183 std::shared_ptr<Rosen::Drawing::Image> image = imgstruct->imageData;
184
185 ROSEN_TRACE_BEGIN(HITRACE_TAG_GRAPHIC_AGP, "BootAnimation::OnDraw in drawRect");
186 Rosen::Drawing::Brush brush;
187 brush.SetColor(Rosen::Drawing::Color::COLOR_BLACK);
188 Rosen::Drawing::Rect bgRect(0.0, 0.0, windowWidth_, windowHeight_);
189 canvas->AttachBrush(brush);
190 canvas->DrawRect(bgRect);
191 canvas->DetachBrush();
192 ROSEN_TRACE_END(HITRACE_TAG_GRAPHIC_AGP);
193 ROSEN_TRACE_BEGIN(HITRACE_TAG_GRAPHIC_AGP, "BootAnimation::OnDraw in drawImageRect");
194 Rosen::Drawing::Rect rect(pointX_, pointY_, pointX_ + realWidth_, pointY_ + realHeight_);
195 Rosen::Drawing::SamplingOptions samplingOptions;
196 canvas->DrawImageRect(*image, rect, samplingOptions);
197 imageVector_[curNo].reset();
198 ROSEN_TRACE_END(HITRACE_TAG_GRAPHIC_AGP);
199 return true;
200 }
201 } // namespace OHOS
202