1 /*
2 * Copyright (c) 2025 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 "feature/lpp/lpp_video_handler.h"
16
17 #include "rs_trace.h"
18
19 #include "common/rs_optional_trace.h"
20 #include "pipeline/main_thread/rs_main_thread.h"
21 #include "platform/common/rs_log.h"
22 namespace OHOS::Rosen {
Instance()23 LppVideoHandler& LppVideoHandler::Instance()
24 {
25 static LppVideoHandler instance;
26 return instance;
27 }
28
ConsumeAndUpdateLppBuffer(const std::shared_ptr<RSSurfaceRenderNode> & surfaceNode)29 void LppVideoHandler::ConsumeAndUpdateLppBuffer(const std::shared_ptr<RSSurfaceRenderNode>& surfaceNode)
30 {
31 std::lock_guard<std::mutex> lock(mutex_);
32 std::shared_ptr<RSSurfaceHandler> surfaceHandler;
33 if (UNLIKELY(surfaceNode == nullptr) || (surfaceHandler = surfaceNode->GetMutableRSSurfaceHandler()) == nullptr ||
34 surfaceHandler->GetSourceType() != OHSurfaceSource::OH_SURFACE_SOURCE_LOWPOWERVIDEO) {
35 return;
36 }
37
38 const auto& consumer = surfaceHandler->GetConsumer();
39 if (consumer == nullptr) {
40 return;
41 }
42 lowPowerSurfaceNode_.push_back(surfaceNode);
43 sptr<SurfaceBuffer> buffer = nullptr;
44 sptr<SyncFence> acquireFence = SyncFence::InvalidFence();
45 int64_t timestamp = 0;
46 std::vector<Rect> damages;
47 consumer->AcquireBuffer(buffer, acquireFence, timestamp, damages, true);
48 if (buffer == nullptr) {
49 return;
50 }
51 std::shared_ptr<RSSurfaceHandler::SurfaceBufferEntry> surfaceBuffer =
52 std::make_shared<RSSurfaceHandler::SurfaceBufferEntry>();
53 surfaceBuffer->buffer = buffer;
54 surfaceBuffer->acquireFence = acquireFence;
55 surfaceBuffer->timestamp = timestamp;
56 RSBaseRenderUtil::MergeBufferDamages(surfaceBuffer->damageRect, damages);
57 if (surfaceBuffer->damageRect.h <= 0 || surfaceBuffer->damageRect.w <= 0) {
58 RS_LOGW("RsDebug ConsumerLowPowerBuffer(id: %{public}" PRIu64 ") buffer damage is invalid",
59 surfaceHandler->GetNodeId());
60 }
61 surfaceBuffer->damageRect.y =
62 surfaceBuffer->buffer->GetHeight() - surfaceBuffer->damageRect.y - surfaceBuffer->damageRect.h;
63 surfaceHandler->ConsumeAndUpdateBuffer(*surfaceBuffer);
64 RS_TRACE_NAME_FMT("ConsumeAndUpdateLowPowerBuffer node: [%lu]", surfaceHandler->GetNodeId());
65 surfaceBuffer = nullptr;
66 }
67
JudgeRsDrawLppState(bool needDrawFrame,bool doDirectComposition)68 void LppVideoHandler::JudgeRsDrawLppState(bool needDrawFrame, bool doDirectComposition)
69 {
70 std::lock_guard<std::mutex> lock(mutex_);
71 bool requestVsync = false;
72 for (const auto& surfaceNode : lowPowerSurfaceNode_) {
73 sptr<IConsumerSurface> consumer;
74 if (UNLIKELY(surfaceNode == nullptr) ||
75 surfaceNode->GetAbilityState() == RSSurfaceNodeAbilityState::BACKGROUND ||
76 surfaceNode->GetMutableRSSurfaceHandler() == nullptr ||
77 (consumer = surfaceNode->GetMutableRSSurfaceHandler()->GetConsumer()) == nullptr) {
78 continue;
79 }
80
81 bool isHardware = !(surfaceNode->IsHardwareForcedDisabled());
82 bool requestNextVsyncForLpp = false;
83 bool isShbDrawLpp = true;
84
85 if (!needDrawFrame) {
86 // Render nothing to update
87 requestNextVsyncForLpp = true;
88 isShbDrawLpp = false;
89 } else {
90 if (!doDirectComposition && !isHardware) {
91 // GPU
92 requestNextVsyncForLpp = true;
93 isShbDrawLpp = false;
94 }
95 if (doDirectComposition || (!doDirectComposition && isHardware)) {
96 // Hareware
97 requestNextVsyncForLpp = false;
98 isShbDrawLpp = true;
99 }
100 }
101
102 if (hasVirtualMirrorDisplay_.load()) {
103 // Virtual screen needs to keep Vsync awake
104 RS_TRACE_NAME_FMT("Virtual screen needs to keep Vsync awake");
105 requestNextVsyncForLpp = true;
106 }
107 if (consumer->SetLppDrawSource(isShbDrawLpp, requestNextVsyncForLpp) != GSError::GSERROR_OK) {
108 RS_TRACE_NAME_FMT("Stop By SetLppDrawSource");
109 requestNextVsyncForLpp = false;
110 }
111 requestVsync = requestVsync || requestNextVsyncForLpp;
112 }
113 if (requestVsync) {
114 RSMainThread::Instance()->RequestNextVSync();
115 }
116 }
117
SetHasVirtualMirrorDisplay(bool hasVirtualMirrorDisplay)118 void LppVideoHandler::SetHasVirtualMirrorDisplay(bool hasVirtualMirrorDisplay)
119 {
120 hasVirtualMirrorDisplay_.store(hasVirtualMirrorDisplay);
121 }
122
ClearLppSurfaceNode()123 void LppVideoHandler::ClearLppSurfaceNode()
124 {
125 std::lock_guard<std::mutex> lock(mutex_);
126 lowPowerSurfaceNode_.clear();
127 }
128 } // namespace OHOS::Rosen