• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
16 
17 #include "rs_rcd_surface_render_node_drawable.h"
18 #include <fstream>
19 #include <filesystem>
20 #include "common/rs_singleton.h"
21 #include "common/rs_optional_trace.h"
22 #include "params/rs_rcd_render_params.h"
23 #include "platform/common/rs_log.h"
24 #include "feature/round_corner_display/rs_rcd_render_listener.h"
25 #include "feature/round_corner_display/rs_rcd_surface_render_node.h"
26 #include "feature/round_corner_display/rs_rcd_render_visitor.h"
27 #include "feature/round_corner_display/rs_round_corner_display_manager.h"
28 
29 namespace OHOS::Rosen::DrawableV2 {
30 
31 const unsigned long long PRIV_USAGE_FBC_CLD_LAYER = 1ULL << 56; // 56 means the buffer usage is hardware
32 const int32_t BUFFER_TIME_OUT = 500;
33 
34 RSRcdSurfaceRenderNodeDrawable::Registrar RSRcdSurfaceRenderNodeDrawable::instance_;
35 
RSRcdSurfaceRenderNodeDrawable(std::shared_ptr<const RSRenderNode> && node)36 RSRcdSurfaceRenderNodeDrawable::RSRcdSurfaceRenderNodeDrawable(std::shared_ptr<const RSRenderNode> &&node)
37     : RSRenderNodeDrawable(std::move(node)), syncDirtyManager_(std::make_shared<RSDirtyRegionManager>(true))
38 {
39     auto nodeSp = std::const_pointer_cast<RSRenderNode>(node);
40     auto rcdNode = std::static_pointer_cast<RSRcdSurfaceRenderNode>(nodeSp);
41     surfaceHandler_ = rcdNode->GetMutableRSSurfaceHandler();
42 }
43 
PrepareResourceBuffer()44 bool RSRcdSurfaceRenderNodeDrawable::PrepareResourceBuffer()
45 {
46     if (!IsSurfaceCreated()) {
47         sptr<IBufferConsumerListener> listener = new RSRcdRenderListener(surfaceHandler_);
48         if (listener == nullptr || (!CreateSurface(listener))) {
49             RS_LOGE("RSRcdSurfaceRenderNodeDrawable::PrepareResourceBuffer CreateSurface failed");
50             return false;
51         }
52     }
53     return true;
54 }
55 
CreateSurface(sptr<IBufferConsumerListener> listener)56 bool RSRcdSurfaceRenderNodeDrawable::CreateSurface(sptr<IBufferConsumerListener> listener)
57 {
58     RS_LOGD("RCD: Start RSRcdSurfaceRenderNodeDrawable CreateSurface");
59     if (surfaceHandler_ == nullptr) {
60         RS_LOGE("RSRcdSurfaceRenderNodeDrawable::CreateSurface surfacehandler is null");
61         return false;
62     }
63     auto consumer = surfaceHandler_->GetConsumer();
64     if (consumer != nullptr && surface_ != nullptr) {
65         RS_LOGD("RSRcdSurfaceRenderNodeDrawable::CreateSurface already created, return");
66         return true;
67     }
68     std::string surfaceName = "";
69     RoundCornerDisplayManager::RCDLayerType type = RoundCornerDisplayManager::RCDLayerType::INVALID;
70     if (IsTopSurface()) {
71         surfaceName = "RCDTopSurfaceNode" + std::to_string(renderTargetId_);
72         type = RoundCornerDisplayManager::RCDLayerType::TOP;
73     } else {
74         surfaceName = "RCDBottomSurfaceNode" + std::to_string(renderTargetId_);
75         type = RoundCornerDisplayManager::RCDLayerType::BOTTOM;
76     }
77     consumer = IConsumerSurface::Create(surfaceName.c_str());
78     RSSingleton<RoundCornerDisplayManager>::GetInstance().AddLayer(surfaceName, renderTargetId_, type);
79     if (consumer == nullptr) {
80         RS_LOGE("RSRcdSurfaceRenderNodeDrawable::CreateSurface get consumer surface fail");
81         return false;
82     }
83     SurfaceError ret = consumer->RegisterConsumerListener(listener);
84     if (ret != SURFACE_ERROR_OK) {
85         RS_LOGE("RSRcdSurfaceRenderNodeDrawable::CreateSurface RegisterConsumerListener fail");
86         return false;
87     }
88     consumerListener_ = listener;
89     auto producer = consumer->GetProducer();
90     sptr<Surface> surface = Surface::CreateSurfaceAsProducer(producer);
91     auto client = std::static_pointer_cast<RSRenderServiceClient>(RSIRenderClient::CreateRenderServiceClient());
92     surface_ = client->CreateRSSurface(surface);
93     surfaceCreated_ = true;
94     surfaceHandler_->SetConsumer(consumer);
95     return true;
96 }
97 
IsSurfaceCreated() const98 bool RSRcdSurfaceRenderNodeDrawable::IsSurfaceCreated() const
99 {
100     return surfaceCreated_;
101 }
102 
GetRSSurface() const103 std::shared_ptr<RSSurface> RSRcdSurfaceRenderNodeDrawable::GetRSSurface() const
104 {
105     return surface_;
106 }
107 
GetConsumerListener() const108 sptr<IBufferConsumerListener> RSRcdSurfaceRenderNodeDrawable::GetConsumerListener() const
109 {
110     return consumerListener_;
111 }
112 
113 
ClearBufferCache()114 void RSRcdSurfaceRenderNodeDrawable::ClearBufferCache()
115 {
116     if (surface_ != nullptr) {
117         surface_->ClearBuffer();
118     }
119     if (surfaceHandler_!= nullptr && surfaceHandler_->GetConsumer() != nullptr) {
120         surfaceHandler_->GetConsumer()->GoBackground();
121     }
122 }
123 
GetRenderTargetId() const124 NodeId RSRcdSurfaceRenderNodeDrawable::GetRenderTargetId() const
125 {
126     return renderTargetId_;
127 }
128 
GetRcdBitmap() const129 std::shared_ptr<Drawing::Bitmap> RSRcdSurfaceRenderNodeDrawable::GetRcdBitmap() const
130 {
131     auto params = static_cast<RSRcdRenderParams*>(renderParams_.get());
132     if (params == nullptr) {
133         return nullptr;
134     }
135     return params->GetRcdBitmap();
136 }
137 
138 
GetRcdBufferWidth() const139 uint32_t RSRcdSurfaceRenderNodeDrawable::RSRcdSurfaceRenderNodeDrawable::GetRcdBufferWidth() const
140 {
141     return GetRcdBitmap() != nullptr ? GetRcdBitmap()->GetWidth() : 0;
142 }
143 
GetRcdBufferHeight() const144 uint32_t RSRcdSurfaceRenderNodeDrawable::GetRcdBufferHeight() const
145 {
146     return GetRcdBitmap() != nullptr ? GetRcdBitmap()->GetHeight() : 0;
147 }
148 
GetRcdBufferSize() const149 uint32_t RSRcdSurfaceRenderNodeDrawable::GetRcdBufferSize() const
150 {
151     auto params = static_cast<RSRcdRenderParams*>(renderParams_.get());
152     if (params == nullptr) {
153         return 0;
154     }
155     return params->GetBufferSize();
156 }
157 
SetSurfaceType(uint32_t surfaceType)158 void RSRcdSurfaceRenderNodeDrawable::SetSurfaceType(uint32_t surfaceType)
159 {
160     surfaceType_ = surfaceType;
161 }
162 
IsTopSurface() const163 bool RSRcdSurfaceRenderNodeDrawable::IsTopSurface() const
164 {
165     return surfaceType_ == static_cast<uint32_t>(RCDSurfaceType::TOP);
166 }
167 
IsBottomSurface() const168 bool RSRcdSurfaceRenderNodeDrawable::IsBottomSurface() const
169 {
170     return surfaceType_ == static_cast<uint32_t>(RCDSurfaceType::BOTTOM);
171 }
172 
IsInvalidSurface() const173 bool RSRcdSurfaceRenderNodeDrawable::IsInvalidSurface() const
174 {
175     return surfaceType_ == static_cast<uint32_t>(RCDSurfaceType::INVALID);
176 }
177 
IsRcdEnabled() const178 bool RSRcdSurfaceRenderNodeDrawable::IsRcdEnabled() const
179 {
180     auto params = static_cast<RSRcdRenderParams*>(renderParams_.get());
181     if (params == nullptr) {
182         return false;
183     }
184     return params->GetRcdEnabled();
185 }
186 
IsResourceChanged() const187 bool RSRcdSurfaceRenderNodeDrawable::IsResourceChanged() const
188 {
189     auto params = static_cast<RSRcdRenderParams*>(renderParams_.get());
190     if (params == nullptr) {
191         return false;
192     }
193     return params->GetResourceChanged();
194 }
195 
GetHardenBufferRequestConfig() const196 BufferRequestConfig RSRcdSurfaceRenderNodeDrawable::GetHardenBufferRequestConfig() const
197 {
198     RS_LOGD("RSRcdSurfaceRenderNodeDrawable::GetHardenBufferRequestConfig");
199     BufferRequestConfig config {};
200     config.width = static_cast<int32_t>(GetRcdBufferWidth());
201     if (GetRcdBufferWidth() != 0) {
202         // need to plus 2 while calculating the bufferHeight in hardware dss way
203         config.height = static_cast<int32_t>(GetRcdBufferSize() / GetRcdBufferWidth() + GetRcdBufferHeight() + 2);
204     }
205     config.strideAlignment = 0x8; // default stride is 8 Bytes.  // output parameter, system components can ignore it
206     config.format = GRAPHIC_PIXEL_FMT_RGBA_8888;
207     config.usage = BUFFER_USAGE_HW_RENDER | BUFFER_USAGE_HW_TEXTURE | BUFFER_USAGE_HW_COMPOSER | BUFFER_USAGE_MEM_DMA
208         | PRIV_USAGE_FBC_CLD_LAYER;
209     RS_LOGD("RCD: GetHardenBufferRequestConfig Buffer usage %{public}" PRIu64 ", width %{public}d, height %{public}d",
210         config.usage, config.width, config.height);
211     config.timeout = BUFFER_TIME_OUT; // ms
212     return config;
213 }
214 
ProcessRcdSurfaceRenderNode(std::shared_ptr<RSProcessor> processor)215 bool RSRcdSurfaceRenderNodeDrawable::ProcessRcdSurfaceRenderNode(std::shared_ptr<RSProcessor> processor)
216 {
217     auto renderEngine = RSUniRenderThread::Instance().GetRenderEngine();
218     if (processor == nullptr || IsInvalidSurface() || renderEngine == nullptr) {
219         RS_LOGE("RSRcdSurfaceRenderNodeDrawable RSProcessor is null or node invalid!");
220         return false;
221     }
222     auto params = static_cast<RSRcdRenderParams*>(renderParams_.get());
223     if (!surfaceHandler_ || !params) {
224         RS_LOGE("RSRcdSurfaceRenderNodeDrawable surfaceHandler or params is null!");
225         return false;
226     }
227     sptr<SurfaceBuffer> buffer = surfaceHandler_->GetBuffer();
228     if (!params->GetResourceChanged() && buffer != nullptr) {
229         processor->ProcessRcdSurfaceForRenderThread(*this);
230         return true;
231     }
232 
233     auto rsSurface = std::static_pointer_cast<RSSurfaceOhos>(GetRSSurface());
234     if (rsSurface == nullptr) {
235         RS_LOGE("RSRcdSurfaceRenderNodeDrawable no RSSurface found");
236         return false;
237     }
238     rsSurface->SetTimeOut(GetHardenBufferRequestConfig().timeout);
239     auto renderFrame = renderEngine->RequestFrame(rsSurface,
240         GetHardenBufferRequestConfig(), true, false);
241     if (renderFrame == nullptr) {
242         rsSurface->GetSurface()->CleanCache(true);
243         RS_LOGE("RSRcdSurfaceRenderNodeDrawable Request Frame Failed");
244         return false;
245     }
246     renderFrame->Flush();
247     if (!ConsumeAndUpdateBuffer()) {
248         RS_LOGE("RSRcdRenderVisitor ConsumeAndUpdateBuffer Failed");
249         return false;
250     }
251     ScalingMode scalingMode = ScalingMode::SCALING_MODE_SCALE_TO_WINDOW;
252     if (surfaceHandler_->GetConsumer() && surfaceHandler_->GetBuffer()) {
253         surfaceHandler_->GetConsumer()->SetScalingMode(surfaceHandler_->GetBuffer()->GetSeqNum(), scalingMode);
254     }
255 
256     processor->ProcessRcdSurfaceForRenderThread(*this);
257 
258     return true;
259 }
260 
ConsumeAndUpdateBuffer()261 bool RSRcdSurfaceRenderNodeDrawable::ConsumeAndUpdateBuffer()
262 {
263     auto params = static_cast<RSRcdRenderParams*>(renderParams_.get());
264     if (!surfaceHandler_ || !params) {
265         return false;
266     }
267     auto availableBufferCnt = surfaceHandler_->GetAvailableBufferCount();
268     if (availableBufferCnt <= 0) {
269         // this node has no new buffer, try use old buffer.
270         return true;
271     }
272 
273     auto consumer = surfaceHandler_->GetConsumer();
274     if (consumer == nullptr) {
275         return false;
276     }
277 
278     sptr<SurfaceBuffer> buffer;
279     sptr<SyncFence> acquireFence = SyncFence::InvalidFence();
280     int64_t timestamp = 0;
281     Rect damage;
282     auto ret = consumer->AcquireBuffer(buffer, acquireFence, timestamp, damage);
283     if (buffer == nullptr || ret != SURFACE_ERROR_OK) {
284         RS_LOGE("RsDebug RSRcdSurfaceRenderNode(id: %{public}" PRIu64 ") AcquireBuffer failed(ret: %{public}d)!",
285             surfaceHandler_->GetNodeId(), ret);
286         return false;
287     }
288 
289     surfaceHandler_->SetBuffer(buffer, acquireFence, damage, timestamp);
290 
291     if (!SetHardwareResourceToBuffer()) {
292         RS_LOGE("RSRcdSurfaceRenderNodeDrawable SetHardwareResourceToBuffer Failed!");
293         return false;
294     }
295 
296     surfaceHandler_->SetCurrentFrameBufferConsumed();
297     surfaceHandler_->ReduceAvailableBuffer();
298     return true;
299 }
300 
SetHardwareResourceToBuffer()301 bool RSRcdSurfaceRenderNodeDrawable::SetHardwareResourceToBuffer()
302 {
303     RS_LOGD("RCD: Start RSRcdSurfaceRenderNodeDrawable::SetHardwareResourceToBuffer");
304     auto layerBitmap = GetRcdBitmap();
305     if (!layerBitmap || layerBitmap->IsValid()) {
306         RS_LOGE("LayerBitmap is null or invalid");
307         return false;
308     }
309     sptr<SurfaceBuffer> nodeBuffer = surfaceHandler_->GetBuffer();
310     if (nodeBuffer == nullptr) {
311         RS_LOGE("RSRcdSurfaceRenderNodeDrawable buffer is nullptr");
312         return false;
313     }
314     Drawing::ImageInfo imgInfo = Drawing::ImageInfo::MakeN32Premul(nodeBuffer->GetWidth(), nodeBuffer->GetHeight());
315     if (!layerBitmap->ReadPixels(imgInfo, reinterpret_cast<void*>(nodeBuffer->GetVirAddr()),
316         nodeBuffer->GetStride(), 0, 0)) {
317         RS_LOGE("RSRcdSurfaceRenderNodeDrawable:: copy layerBitmap to buffer failed");
318         return false;
319     }
320     if (!FillHardwareResource(layerBitmap->GetWidth(), layerBitmap->GetHeight())) {
321         RS_LOGE("RSRcdSurfaceRenderNodeDrawable:: copy hardware resource to buffer failed");
322         return false;
323     }
324     return true;
325 }
326 
FillHardwareResource(int width,int height)327 bool RSRcdSurfaceRenderNodeDrawable::FillHardwareResource(int width, int height)
328 {
329     sptr<SurfaceBuffer> nodeBuffer = surfaceHandler_->GetBuffer();
330     if (nodeBuffer == nullptr) {
331         RS_LOGE("RSRcdSurfaceRenderNode buffer is nullptr");
332         return false;
333     }
334     auto params = static_cast<RSRcdRenderParams*>(renderParams_.get());
335     if (GetRcdBufferSize() < 0 || params->GetCldWidth() < 0 || params->GetCldHeight() < 0 || width < 0 ||
336         height < 0) {
337         RS_LOGE("RSRcdSurfaceRenderNode check size failed");
338         return false;
339     }
340     const uint32_t bytesPerPixel = 4; // 4 means four bytes per pixel
341     cldInfo_.cldSize = static_cast<uint32_t>(params->GetBufferSize());
342     cldInfo_.cldWidth = static_cast<uint32_t>(params->GetCldWidth());
343     cldInfo_.cldHeight = static_cast<uint32_t>(params->GetCldHeight());
344     cldInfo_.cldStride = static_cast<uint32_t>(params->GetCldWidth() * bytesPerPixel);
345     cldInfo_.exWidth = static_cast<uint32_t>(width);
346     cldInfo_.exHeight = static_cast<uint32_t>(height);
347 
348     int offset = 0;
349     int offsetCldInfo = 0;
350     int stride = nodeBuffer->GetStride();
351     offsetCldInfo = height * stride;
352     offset = (height + 1) * stride;
353     cldInfo_.cldDataOffset = static_cast<uint32_t>(offset);
354     uint8_t *img = static_cast<uint8_t*>(nodeBuffer->GetVirAddr());
355     uint32_t bufferSize = nodeBuffer->GetSize();
356     if (img == nullptr || offsetCldInfo < 0 || bufferSize < static_cast<uint32_t>(offsetCldInfo) + sizeof(cldInfo_)) {
357         RS_LOGE("[%s] check nodebuffer failed", __func__);
358         return false;
359     }
360     errno_t ret = memcpy_s(reinterpret_cast<void*>(img + offsetCldInfo), sizeof(cldInfo_), &cldInfo_, sizeof(cldInfo_));
361     if (ret != EOK) {
362         RS_LOGE("[%s] memcpy_s failed", __func__);
363         return false;
364     }
365     std::ifstream addBufferFile(params->GetPathBin(), std::ifstream::binary | std::ifstream::in);
366     if (addBufferFile) {
367         addBufferFile.seekg(0, addBufferFile.end);
368         int addBufferSize = addBufferFile.tellg();
369         addBufferFile.seekg(0, addBufferFile.beg);
370         addBufferFile.read(reinterpret_cast<char*>(img + offset), addBufferSize);
371         addBufferFile.close();
372     } else {
373         RS_LOGE("[%{public}s] hardware fopen error", __func__);
374         return false;
375     }
376     return true;
377 }
378 
DoProcessRenderTask(std::shared_ptr<RSProcessor> processor)379 bool RSRcdSurfaceRenderNodeDrawable::DoProcessRenderTask(std::shared_ptr<RSProcessor> processor)
380 {
381     RS_TRACE_BEGIN("RSRcdSurfaceRenderNodeDrawable:DoProcessRenderTask");
382     if (!IsRcdEnabled()) {
383         RS_LOGD("RSRcdSurfaceRenderNodeDrawable::DoProcessRenderTask: Draw skip, rcd disabled");
384         RS_TRACE_END();
385         return false;
386     }
387     if (!processor) {
388         RS_LOGE("RCD: processor is null");
389         RS_TRACE_END();
390         return false;
391     }
392     auto res = ProcessRcdSurfaceRenderNode(processor);
393     RS_TRACE_END();
394     return res;
395 }
396 
GetCldInfo() const397 const CldInfo& RSRcdSurfaceRenderNodeDrawable::GetCldInfo() const
398 {
399     return cldInfo_;
400 }
401 
SetRenderTargetId(NodeId id)402 void RSRcdSurfaceRenderNodeDrawable::SetRenderTargetId(NodeId id)
403 {
404     renderTargetId_ = id;
405 }
406 
OnGenerate(std::shared_ptr<const RSRenderNode> node)407 RSRenderNodeDrawable::Ptr RSRcdSurfaceRenderNodeDrawable::OnGenerate(std::shared_ptr<const RSRenderNode> node)
408 {
409     return new RSRcdSurfaceRenderNodeDrawable(std::move(node));
410 }
411 } // namespace OHOS::Rosen::DrawableV2
412