1 /*
2 * Copyright (c) 2021 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 "rs_screen.h"
17
18 #include <cinttypes>
19
20 #include "string_utils.h"
21
22 namespace OHOS {
23 namespace Rosen {
24 using namespace HiviewDFX;
25
26 namespace impl {
27 namespace detail {
28 template <int ROTATE_DEGREES>
RotateMatrix()29 constexpr SkMatrix RotateMatrix()
30 {
31 return SkMatrix().setRotate(ROTATE_DEGREES);
32 }
33 } // namespace detail
34
RSScreen(ScreenId id,bool isVirtual,std::shared_ptr<HdiOutput> output,sptr<Surface> surface)35 RSScreen::RSScreen(ScreenId id,
36 bool isVirtual,
37 std::shared_ptr<HdiOutput> output,
38 sptr<Surface> surface)
39 : id_(id),
40 isVirtual_(isVirtual),
41 hdiOutput_(std::move(output)),
42 producerSurface_(std::move(surface))
43 {
44 if (!IsVirtual()) {
45 name_ = "Screen_" + std::to_string(id_);
46 PhysicalScreenInit();
47 }
48 }
49
RSScreen(const VirtualScreenConfigs & configs)50 RSScreen::RSScreen(const VirtualScreenConfigs &configs)
51 : id_(configs.id),
52 mirrorId_(configs.mirrorId),
53 name_(configs.name),
54 width_(configs.width),
55 height_(configs.height),
56 isVirtual_(true),
57 producerSurface_(configs.surface)
58 {
59 }
60
~RSScreen()61 RSScreen::~RSScreen() noexcept
62 {
63 }
64
PhysicalScreenInit()65 void RSScreen::PhysicalScreenInit() noexcept
66 {
67 hdiScreen_ = HdiScreen::CreateHdiScreen(ScreenPhysicalId(id_));
68 if (hdiScreen_ == nullptr) {
69 HiLog::Error(LOG_LABEL, "%{public}s: RSScreen(id %{public}" PRIu64 ") failed to CreateHdiScreens.",
70 __func__, id_);
71 return;
72 }
73
74 hdiScreen_->Init();
75 if (hdiScreen_->GetScreenSupportedModes(supportedModes_) < 0) {
76 HiLog::Error(LOG_LABEL, "%{public}s: RSScreen(id %{public}" PRIu64 ") failed to GetScreenSupportedModes.",
77 __func__, id_);
78 }
79 if (hdiScreen_->GetScreenCapability(capability_) < 0) {
80 HiLog::Error(LOG_LABEL, "%{public}s: RSScreen(id %{public}" PRIu64 ") failed to GetScreenCapability.",
81 __func__, id_);
82 }
83 auto status = DispPowerStatus::POWER_STATUS_ON;
84 if (hdiScreen_->SetScreenPowerStatus(status) < 0) {
85 HiLog::Error(LOG_LABEL, "%{public}s: RSScreen(id %{public}" PRIu64 ") failed to SetScreenPowerStatus.",
86 __func__, id_);
87 }
88 auto activeMode = GetActiveMode();
89 if (activeMode) {
90 width_ = activeMode->width;
91 height_ = activeMode->height;
92 }
93 if (hdiScreen_->GetScreenPowerStatus(powerStatus_) < 0) {
94 powerStatus_ = static_cast<DispPowerStatus>(INVALID_POWER_STATUS);
95 }
96 }
97
Id() const98 ScreenId RSScreen::Id() const
99 {
100 return id_;
101 }
102
MirrorId() const103 ScreenId RSScreen::MirrorId() const
104 {
105 return mirrorId_;
106 }
107
SetMirror(ScreenId mirrorId)108 void RSScreen::SetMirror(ScreenId mirrorId)
109 {
110 mirrorId_ = mirrorId;
111 }
112
Name() const113 const std::string& RSScreen::Name() const
114 {
115 return name_;
116 }
117
Width() const118 uint32_t RSScreen::Width() const
119 {
120 return width_;
121 }
122
Height() const123 uint32_t RSScreen::Height() const
124 {
125 return height_;
126 }
127
IsEnable() const128 bool RSScreen::IsEnable() const
129 {
130 if (id_ == INVALID_SCREEN_ID) {
131 return false;
132 }
133
134 if (!hdiOutput_ && !producerSurface_) {
135 return false;
136 }
137
138 // [PLANNING]: maybe need more information to judge whether this screen is enable.
139 return true;
140 }
141
IsVirtual() const142 bool RSScreen::IsVirtual() const
143 {
144 return isVirtual_;
145 }
146
SetActiveMode(uint32_t modeId)147 void RSScreen::SetActiveMode(uint32_t modeId)
148 {
149 if (IsVirtual()) {
150 HiLog::Warn(LOG_LABEL, "%{public}s: virtual screen not support SetActiveMode.\n", __func__);
151 return;
152 }
153
154 if (modeId >= supportedModes_.size()) {
155 HiLog::Error(LOG_LABEL, "%{public}s: set fails because the index is out of bounds.\n", __func__);
156 return;
157 }
158 int32_t selectModeId = supportedModes_[modeId].id;
159 if (hdiScreen_->SetScreenMode(static_cast<uint32_t>(selectModeId)) < 0) {
160 HiLog::Error(LOG_LABEL, "%{public}s: Hdi SetScreenMode fails.\n", __func__);
161 return;
162 }
163 auto activeMode = GetActiveMode();
164 if (activeMode) {
165 width_ = activeMode->width;
166 height_ = activeMode->height;
167 }
168 }
169
GetActiveModePosByModeId(int32_t modeId) const170 int32_t RSScreen::GetActiveModePosByModeId(int32_t modeId) const
171 {
172 decltype(supportedModes_.size()) modeIndex = 0;
173 for (; modeIndex < supportedModes_.size(); ++modeIndex) {
174 if (supportedModes_[modeIndex].id == modeId) {
175 return static_cast<int32_t>(modeIndex);
176 }
177 }
178 return -1;
179 }
180
SetPowerStatus(uint32_t powerStatus)181 void RSScreen::SetPowerStatus(uint32_t powerStatus)
182 {
183 if (IsVirtual()) {
184 HiLog::Warn(LOG_LABEL, "%{public}s: virtual screen not support SetPowerStatus.\n", __func__);
185 return;
186 }
187
188 HiLog::Info(LOG_LABEL, "SetPowerStatus, status is %{public}u", powerStatus);
189 if (hdiScreen_->SetScreenPowerStatus(static_cast<DispPowerStatus>(powerStatus)) < 0) {
190 return;
191 }
192
193 if (powerStatus == DispPowerStatus::POWER_STATUS_ON) {
194 HiLog::Info(LOG_LABEL, "Enable hardware vsync");
195 if (hdiScreen_->SetScreenVsyncEnabled(true) != DISPLAY_SUCCESS) {
196 HiLog::Error(LOG_LABEL, "SetScreenVsyncEnabled failed");
197 }
198 }
199 }
200
GetActiveMode() const201 std::optional<DisplayModeInfo> RSScreen::GetActiveMode() const
202 {
203 if (IsVirtual()) {
204 HiLog::Warn(LOG_LABEL, "%{public}s: virtual screen not support GetActiveMode.\n", __func__);
205 return {};
206 }
207
208 uint32_t modeId = 0;
209
210 if (hdiScreen_ == nullptr) {
211 HiLog::Error(LOG_LABEL, "%{public}s: RSScreen(id %{public}" PRIu64 ") hdiScreen is null.",
212 __func__, id_);
213 return {};
214 }
215
216 if (hdiScreen_->GetScreenMode(modeId) < 0) {
217 HiLog::Error(LOG_LABEL, "%{public}s: RSScreen(id %{public}" PRIu64 ") GetScreenMode failed.",
218 __func__, id_);
219 return {};
220 }
221
222 auto iter = std::find_if(supportedModes_.cbegin(), supportedModes_.cend(),
223 [modeId](const auto &mode) { return mode.id == modeId; });
224 if (iter == supportedModes_.cend()) {
225 return {};
226 }
227
228 return *iter;
229 }
230
GetSupportedModes() const231 const std::vector<DisplayModeInfo>& RSScreen::GetSupportedModes() const
232 {
233 return supportedModes_;
234 }
235
GetCapability() const236 const DisplayCapability& RSScreen::GetCapability() const
237 {
238 return capability_;
239 }
240
GetPowerStatus() const241 uint32_t RSScreen::GetPowerStatus() const
242 {
243 if (IsVirtual()) {
244 HiLog::Warn(LOG_LABEL, "%{public}s: virtual screen not support GetPowerStatus.\n", __func__);
245 return ScreenPowerStatus::INVALID_POWER_STATUS;
246 }
247
248 DispPowerStatus status;
249 if (hdiScreen_->GetScreenPowerStatus(status) < 0) {
250 return INVALID_POWER_STATUS;
251 }
252 return static_cast<uint32_t>(status);
253 }
254
GetOutput() const255 std::shared_ptr<HdiOutput> RSScreen::GetOutput() const
256 {
257 return hdiOutput_;
258 }
259
GetProducerSurface() const260 sptr<Surface> RSScreen::GetProducerSurface() const
261 {
262 return producerSurface_;
263 }
264
SetProducerSurface(sptr<Surface> producerSurface)265 void RSScreen::SetProducerSurface(sptr<Surface> producerSurface)
266 {
267 producerSurface_ = producerSurface;
268 }
269
ModeInfoDump(std::string & dumpString)270 void RSScreen::ModeInfoDump(std::string& dumpString)
271 {
272 decltype(supportedModes_.size()) modeIndex = 0;
273 for (; modeIndex < supportedModes_.size(); ++modeIndex) {
274 AppendFormat(dumpString, " supportedMode[%d]: %dx%d, refreshrate=%d\n",
275 modeIndex, supportedModes_[modeIndex].width,
276 supportedModes_[modeIndex].height, supportedModes_[modeIndex].freshRate);
277 }
278 std::optional<DisplayModeInfo> activeMode = GetActiveMode();
279 if (activeMode) {
280 AppendFormat(dumpString, " activeMode: %dx%d, refreshrate=%d\n",
281 activeMode->width, activeMode->height, activeMode->freshRate);
282 }
283 }
284
CapabilityTypeDump(InterfaceType capabilityType,std::string & dumpString)285 void RSScreen::CapabilityTypeDump(InterfaceType capabilityType, std::string& dumpString)
286 {
287 dumpString += "type=";
288 switch (capability_.type) {
289 case DISP_INTF_HDMI: {
290 dumpString += "DISP_INTF_HDMI, ";
291 break;
292 }
293 case DISP_INTF_LCD: {
294 dumpString += "DISP_INTF_LCD, ";
295 break;
296 }
297 case DISP_INTF_BT1120: {
298 dumpString += "DISP_INTF_BT1120, ";
299 break;
300 }
301 case DISP_INTF_BT656: {
302 dumpString += "DISP_INTF_BT656, ";
303 break;
304 }
305 default:
306 dumpString += "INVILID_DISP_INTF, ";
307 break;
308 }
309 }
310
CapabilityDump(std::string & dumpString)311 void RSScreen::CapabilityDump(std::string& dumpString)
312 {
313 AppendFormat(dumpString, " capability: name=%s, phywidth=%d, phyheight=%d,"
314 "supportlayers=%d, virtualDispCount=%d, propCount=%d, ",
315 capability_.name, capability_.phyWidth, capability_.phyHeight,
316 capability_.supportLayers, capability_.virtualDispCount, capability_.propertyCount);
317 CapabilityTypeDump(capability_.type, dumpString);
318 dumpString += "supportWriteBack=";
319 dumpString += (capability_.supportWriteBack) ? "true" : "false";
320 dumpString += "\n";
321 PropDump(dumpString);
322 }
323
PropDump(std::string & dumpString)324 void RSScreen::PropDump(std::string& dumpString)
325 {
326 decltype(capability_.propertyCount) propIndex = 0;
327 for (; propIndex < capability_.propertyCount; ++propIndex) {
328 AppendFormat(dumpString, "prop[%u]: name=%s, propid=%d, value=%d\n",
329 propIndex, capability_.props[propIndex].name, capability_.props[propIndex].propId,
330 capability_.props[propIndex].value);
331 }
332 }
333
PowerStatusDump(DispPowerStatus powerStatus,std::string & dumpString)334 void RSScreen::PowerStatusDump(DispPowerStatus powerStatus, std::string& dumpString)
335 {
336 dumpString += "powerstatus=";
337 switch (powerStatus) {
338 case POWER_STATUS_ON: {
339 dumpString += "POWER_STATUS_ON";
340 break;
341 }
342 case POWER_STATUS_STANDBY: {
343 dumpString += "POWER_STATUS_STANDBY";
344 break;
345 }
346 case POWER_STATUS_SUSPEND: {
347 dumpString += "POWER_STATUS_SUSPEND";
348 break;
349 }
350 case POWER_STATUS_OFF: {
351 dumpString += "POWER_STATUS_OFF";
352 break;
353 }
354 case POWER_STATUS_BUTT: {
355 dumpString += "POWER_STATUS_BUTT";
356 break;
357 }
358 default:
359 dumpString += "INVALID_POWER_STATUS";
360 break;
361 }
362 }
363
364
DisplayDump(int32_t screenIndex,std::string & dumpString)365 void RSScreen::DisplayDump(int32_t screenIndex, std::string& dumpString)
366 {
367 dumpString += "-- ScreenInfo\n";
368 if (IsVirtual()) {
369 dumpString += "screen[" + std::to_string(screenIndex) + "]: ";
370 dumpString += "id=";
371 dumpString += (id_ == INVALID_SCREEN_ID) ? "INVALID_SCREEN_ID" : std::to_string(id_);
372 dumpString += ", ";
373 dumpString += "mirrorId=";
374 dumpString += (mirrorId_ == INVALID_SCREEN_ID) ? "INVALID_SCREEN_ID" : std::to_string(mirrorId_);
375 dumpString += ", ";
376 AppendFormat(dumpString, "%dx%d, isvirtual=true\n", width_, height_);
377 } else {
378 dumpString += "screen[" + std::to_string(screenIndex) + "]: ";
379 dumpString += "id=";
380 dumpString += (id_ == INVALID_SCREEN_ID) ? "INVALID_SCREEN_ID" : std::to_string(id_);
381 dumpString += ", ";
382 PowerStatusDump(powerStatus_, dumpString);
383 dumpString += "\n";
384 ModeInfoDump(dumpString);
385 CapabilityDump(dumpString);
386 }
387 }
388
SurfaceDump(int32_t screenIndex,std::string & dumpString)389 void RSScreen::SurfaceDump(int32_t screenIndex, std::string& dumpString)
390 {
391 if (hdiOutput_ == nullptr) {
392 return;
393 }
394 hdiOutput_->Dump(dumpString);
395 }
396
FpsDump(int32_t screenIndex,std::string & dumpString,std::string & arg)397 void RSScreen::FpsDump(int32_t screenIndex, std::string& dumpString, std::string& arg)
398 {
399 if (hdiOutput_ == nullptr) {
400 return;
401 }
402 hdiOutput_->DumpFps(dumpString, arg);
403 }
404
SetScreenBacklight(uint32_t level)405 void RSScreen::SetScreenBacklight(uint32_t level)
406 {
407 if (IsVirtual()) {
408 HiLog::Warn(LOG_LABEL, "%{public}s: virtual screen not support SetScreenBacklight.\n", __func__);
409 return;
410 }
411 if (hdiScreen_->SetScreenBacklight(level) < 0) {
412 return;
413 }
414 }
415
GetScreenBacklight() const416 int32_t RSScreen::GetScreenBacklight() const
417 {
418 if (IsVirtual()) {
419 HiLog::Warn(LOG_LABEL, "%{public}s: virtual screen not support GetScreenBacklight.\n", __func__);
420 return INVALID_BACKLIGHT_VALUE;
421 }
422 uint32_t level = 0;
423 if (hdiScreen_->GetScreenBacklight(level) < 0) {
424 return INVALID_BACKLIGHT_VALUE;
425 }
426 return static_cast<int32_t>(level);
427 }
428
GetScreenSupportedColorGamuts(std::vector<ScreenColorGamut> & mode) const429 int32_t RSScreen::GetScreenSupportedColorGamuts(std::vector<ScreenColorGamut> &mode) const
430 {
431 if (IsVirtual()) {
432 mode.clear();
433 mode = supportedVirtualColorGamuts_;
434 return StatusCode::SUCCESS;
435 }
436 std::vector<ColorGamut> hdiMode;
437 int32_t result = hdiScreen_->GetScreenSupportedColorGamuts(hdiMode);
438 if (result == DispErrCode::DISPLAY_SUCCESS) {
439 mode.clear();
440 for (auto m : hdiMode) {
441 mode.push_back(static_cast<ScreenColorGamut>(m));
442 }
443 return StatusCode::SUCCESS;
444 }
445 return StatusCode::HDI_ERROR;
446 }
447
GetScreenColorGamut(ScreenColorGamut & mode) const448 int32_t RSScreen::GetScreenColorGamut(ScreenColorGamut &mode) const
449 {
450 if (IsVirtual()) {
451 mode = supportedVirtualColorGamuts_[currentVirtualColorGamutIdx_];
452 return StatusCode::SUCCESS;
453 }
454 ColorGamut hdiMode;
455 int32_t result = hdiScreen_->GetScreenColorGamut(hdiMode);
456 if (result == DispErrCode::DISPLAY_SUCCESS) {
457 mode = static_cast<ScreenColorGamut>(hdiMode);
458 return StatusCode::SUCCESS;
459 }
460 return StatusCode::HDI_ERROR;
461 }
462
SetScreenColorGamut(int32_t modeIdx)463 int32_t RSScreen::SetScreenColorGamut(int32_t modeIdx)
464 {
465 if (IsVirtual()) {
466 if (modeIdx >= static_cast<int32_t>(supportedVirtualColorGamuts_.size())) {
467 return StatusCode::INVALID_ARGUMENTS;
468 }
469 currentVirtualColorGamutIdx_ = modeIdx;
470 return StatusCode::SUCCESS;
471 }
472 std::vector<ColorGamut> hdiMode;
473 if (hdiScreen_->GetScreenSupportedColorGamuts(hdiMode) != DispErrCode::DISPLAY_SUCCESS) {
474 return StatusCode::HDI_ERROR;
475 }
476 if (modeIdx >= static_cast<int32_t>(hdiMode.size())) {
477 return StatusCode::INVALID_ARGUMENTS;
478 }
479 int32_t result = hdiScreen_->SetScreenColorGamut(hdiMode[modeIdx]);
480 if (result == DispErrCode::DISPLAY_SUCCESS) {
481 return StatusCode::SUCCESS;
482 }
483 return StatusCode::HDI_ERROR;
484 }
485
SetScreenGamutMap(ScreenGamutMap mode)486 int32_t RSScreen::SetScreenGamutMap(ScreenGamutMap mode)
487 {
488 if (IsVirtual()) {
489 currentVirtualGamutMap_ = mode;
490 return StatusCode::SUCCESS;
491 }
492 int32_t result = hdiScreen_->SetScreenGamutMap(static_cast<GamutMap>(mode));
493 if (result == DispErrCode::DISPLAY_SUCCESS) {
494 return StatusCode::SUCCESS;
495 }
496 return StatusCode::HDI_ERROR;
497 }
498
GetScreenGamutMap(ScreenGamutMap & mode) const499 int32_t RSScreen::GetScreenGamutMap(ScreenGamutMap &mode) const
500 {
501 if (IsVirtual()) {
502 mode = currentVirtualGamutMap_;
503 return StatusCode::SUCCESS;
504 }
505 GamutMap hdiMode;
506 int32_t result = hdiScreen_->GetScreenGamutMap(hdiMode);
507 if (result == DispErrCode::DISPLAY_SUCCESS) {
508 mode = static_cast<ScreenGamutMap>(hdiMode);
509 return StatusCode::SUCCESS;
510 }
511 return StatusCode::HDI_ERROR;
512 }
513
UpdateRotationMatrix()514 void RSScreen::UpdateRotationMatrix()
515 {
516 switch (rotation_) {
517 case ScreenRotation::ROTATION_90: {
518 // rotate 90 degrees anticlockwise
519 rotationMatrix_ = detail::RotateMatrix<-90>().postTranslate(0.0, static_cast<float>(height_));
520 break;
521 }
522 case ScreenRotation::ROTATION_180: {
523 // rotate 180 degrees
524 rotationMatrix_ = detail::RotateMatrix<180>().postTranslate(
525 static_cast<float>(width_), static_cast<float>(height_));
526 break;
527 }
528 case ScreenRotation::ROTATION_270: {
529 // rotate 270 degrees anticlockwise
530 rotationMatrix_ = detail::RotateMatrix<-270>().postTranslate(static_cast<float>(width_), 0.0);
531 break;
532 }
533 default: {
534 rotationMatrix_ = SkMatrix();
535 break;
536 }
537 };
538 }
539
GetRotationMatrix() const540 SkMatrix RSScreen::GetRotationMatrix() const
541 {
542 return rotationMatrix_;
543 }
544
SetRotation(ScreenRotation rotation)545 bool RSScreen::SetRotation(ScreenRotation rotation)
546 {
547 if (rotation_ != rotation) {
548 rotation_ = rotation;
549 UpdateRotationMatrix();
550 }
551
552 return true;
553 }
554
GetRotation() const555 ScreenRotation RSScreen::GetRotation() const
556 {
557 return rotation_;
558 }
559 } // namespace impl
560 } // namespace Rosen
561 } // namespace OHOS
562