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