• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
16 #include "drawable/rs_canvas_drawing_render_node_drawable.h"
17 
18 #include "common/rs_background_thread.h"
19 #include "common/rs_common_def.h"
20 #include "common/rs_optional_trace.h"
21 #include "feature/uifirst/rs_sub_thread_manager.h"
22 #include "memory/rs_tag_tracker.h"
23 #include "offscreen_render/rs_offscreen_render_thread.h"
24 #include "params/rs_canvas_drawing_render_params.h"
25 #include "pipeline/render_thread/rs_uni_render_thread.h"
26 #include "pipeline/render_thread/rs_uni_render_util.h"
27 #include "pipeline/main_thread/rs_main_thread.h"
28 #include "pipeline/rs_task_dispatcher.h"
29 #include "pipeline/sk_resource_manager.h"
30 #include "platform/common/rs_log.h"
31 #include "include/gpu/vk/GrVulkanTrackerInterface.h"
32 
33 #ifdef RS_PROFILER_ENABLED
34 #include "rs_profiler_capture_recorder.h"
35 #endif
36 
37 namespace OHOS::Rosen::DrawableV2 {
38 namespace {
39     constexpr int EDGE_WIDTH_LIMIT = 1000;
40     constexpr float DRAW_REGION_FOR_DFX_BORDER = 5.0f;
41 }
42 RSCanvasDrawingRenderNodeDrawable::Registrar RSCanvasDrawingRenderNodeDrawable::instance_;
43 
RSCanvasDrawingRenderNodeDrawable(std::shared_ptr<const RSRenderNode> && node)44 RSCanvasDrawingRenderNodeDrawable::RSCanvasDrawingRenderNodeDrawable(std::shared_ptr<const RSRenderNode>&& node)
45     : RSRenderNodeDrawable(std::move(node))
46 {
47     auto renderNode = renderNode_.lock();
48     if (renderNode == nullptr) {
49         return;
50     }
51     auto nodeSp = std::const_pointer_cast<RSRenderNode>(renderNode);
52     auto canvasDrawingRenderNode = std::static_pointer_cast<RSCanvasDrawingRenderNode>(nodeSp);
53     canvasDrawingRenderNode->InitRenderContent();
54 }
55 
~RSCanvasDrawingRenderNodeDrawable()56 RSCanvasDrawingRenderNodeDrawable::~RSCanvasDrawingRenderNodeDrawable()
57 {
58 #if (defined(RS_ENABLE_GL) || defined(RS_ENABLE_VK))
59     if (curThreadInfo_.second && surface_) {
60         curThreadInfo_.second(std::move(surface_));
61     }
62 #endif
63 }
64 
OnGenerate(std::shared_ptr<const RSRenderNode> node)65 RSRenderNodeDrawable::Ptr RSCanvasDrawingRenderNodeDrawable::OnGenerate(std::shared_ptr<const RSRenderNode> node)
66 {
67     return new RSCanvasDrawingRenderNodeDrawable(std::move(node));
68 }
69 
OnDraw(Drawing::Canvas & canvas)70 void RSCanvasDrawingRenderNodeDrawable::OnDraw(Drawing::Canvas& canvas)
71 {
72     SetDrawSkipType(DrawSkipType::NONE);
73     std::unique_lock<std::recursive_mutex> lock(drawableMutex_);
74     if (!ShouldPaint()) {
75         SetDrawSkipType(DrawSkipType::SHOULD_NOT_PAINT);
76         return;
77     }
78     const auto& params = GetRenderParams();
79     if (UNLIKELY(!params)) {
80         SetDrawSkipType(DrawSkipType::RENDER_PARAMS_NULL);
81         RS_LOGE("RSCanvasDrawingRenderNodeDrawable params is null!");
82         return;
83     }
84     if (params->GetCanvasDrawingSurfaceChanged()) {
85         ResetSurface();
86         params->SetCanvasDrawingSurfaceChanged(false);
87     }
88     Drawing::GPUResourceTag::SetCurrentNodeId(GetId());
89     auto paintFilterCanvas = static_cast<RSPaintFilterCanvas*>(&canvas);
90     RSAutoCanvasRestore acr(paintFilterCanvas, RSPaintFilterCanvas::SaveType::kCanvasAndAlpha);
91     if (!canvas.GetRecordingState()) {
92         params->ApplyAlphaAndMatrixToCanvas(*paintFilterCanvas);
93     }
94 
95     auto& uniParam = RSUniRenderThread::Instance().GetRSRenderThreadParams();
96     SetOcclusionCullingEnabled((!uniParam || uniParam->IsOpDropped()) && GetOpDropped());
97     if (IsOcclusionCullingEnabled() && QuickReject(canvas, params->GetLocalDrawRect())) {
98         SetDrawSkipType(DrawSkipType::OCCLUSION_SKIP);
99         return;
100     }
101 
102     auto threadIdx = paintFilterCanvas->GetParallelThreadIdx();
103     auto clearFunc = [idx = threadIdx](std::shared_ptr<Drawing::Surface> surface) {
104         // The second param is null, 0 is an invalid value.
105         RSUniRenderUtil::ClearNodeCacheSurface(std::move(surface), nullptr, idx, 0);
106     };
107 #if defined(RS_ENABLE_GPU) && defined(RS_ENABLE_PARALLEL_RENDER)
108     auto threadId = paintFilterCanvas->GetIsParallelCanvas() ?
109         RSSubThreadManager::Instance()->GetReThreadIndexMap()[threadIdx] : RSUniRenderThread::Instance().GetTid();
110     SetSurfaceClearFunc({ threadIdx, clearFunc }, threadId);
111 #endif
112 
113     auto& bounds = params->GetBounds();
114     auto surfaceParams = params->GetCanvasDrawingSurfaceParams();
115     if (!InitSurface(surfaceParams.width, surfaceParams.height, *paintFilterCanvas)) {
116         SetDrawSkipType(DrawSkipType::INIT_SURFACE_FAIL);
117         RS_LOGE("Failed to init surface!");
118         return;
119     }
120 
121 #ifdef RS_PROFILER_ENABLED
122         if (auto canvas = RSCaptureRecorder::GetInstance().TryDrawingCanvasCapture(
123             static_cast<float>(canvas_->GetWidth()), static_cast<float>(canvas_->GetHeight()), nodeId_)) {
124             DrawContent(*canvas, bounds);
125             RSCaptureRecorder::GetInstance().EndDrawingCanvasCapture();
126         }
127 #endif
128 
129     // 1. Draw background of this drawing node by the main canvas.
130     DrawBackground(canvas, bounds);
131 
132     // 2. Draw content of this drawing node by the content canvas.
133     DrawRenderContent(canvas, bounds);
134 
135     //if you want to dump canvas_drawing_node as a png
136     DumpCanvasDrawing();
137 
138     auto& captureParam = RSUniRenderThread::GetCaptureParam();
139     bool stopDrawForRangeCapture = (canvas.GetUICapture() &&
140         captureParam.endNodeId_ == GetId() &&
141         captureParam.endNodeId_ != INVALID_NODEID);
142 
143     if (!captureParam.isSoloNodeUiCapture_ && !stopDrawForRangeCapture) {
144         // 3. Draw children of this drawing node by the main canvas.
145         DrawChildren(canvas, bounds);
146     }
147 
148     // 4. Draw foreground of this drawing node by the main canvas.
149     DrawForeground(canvas, bounds);
150 
151     // Draw bounds rect for dfx.
152     DrawRegionForDfx(canvas, bounds);
153 }
154 
CanvasDrawingDumpToPngImpl(std::shared_ptr<Drawing::Bitmap> bitmap,std::string debugNodeId)155 void CanvasDrawingDumpToPngImpl(std::shared_ptr<Drawing::Bitmap> bitmap, std::string debugNodeId)
156 {
157     RS_LOGI("canvas drawing dump beginning");
158     RSBaseRenderUtil::WriteCacheImageRenderNodeToPng(bitmap, debugNodeId);
159 }
160 
DumpCanvasDrawing()161 void RSCanvasDrawingRenderNodeDrawable::DumpCanvasDrawing()
162 {
163     if (image_ == nullptr) {
164         RS_LOGD("No image to drawing");
165         return;
166     }
167 
168     bool enabled = RSSystemParameters::GetDumpCanvasDrawingNodeEnabled();
169     if (!enabled) {
170         return;
171     }
172     std::string debugNodeId = std::to_string(GetId());
173     Drawing::BitmapFormat format = { Drawing::ColorType::COLORTYPE_RGBA_8888, Drawing::AlphaType::ALPHATYPE_PREMUL };
174     std::shared_ptr<Drawing::Bitmap> bitmap = std::make_shared<Drawing::Bitmap>();
175     bitmap->Build(image_->GetWidth(), image_->GetHeight(), format);
176     image_->ReadPixels(*bitmap, 0, 0);
177     std::thread syncDump(CanvasDrawingDumpToPngImpl, bitmap, debugNodeId);
178     syncDump.detach();
179 }
180 
DrawRenderContent(Drawing::Canvas & canvas,const Drawing::Rect & rect)181 void RSCanvasDrawingRenderNodeDrawable::DrawRenderContent(Drawing::Canvas& canvas, const Drawing::Rect& rect)
182 {
183     DrawContent(*canvas_, rect);
184     if (!renderParams_ || !RSUniRenderThread::Instance().GetRSRenderThreadParams()) {
185         return;
186     }
187     SetNeedDraw(false);
188     Rosen::Drawing::Matrix mat;
189     const auto& params = GetRenderParams();
190     if (params == nullptr) {
191         return;
192     }
193 #ifdef RS_ENABLE_GPU
194     RSTagTracker tagTracker(canvas.GetGPUContext(), RSTagTracker::SOURCETYPE::SOURCE_DRAWRENDERCONTENT);
195 #endif
196     auto& frameRect = params->GetFrameRect();
197     if (RSPropertiesPainter::GetGravityMatrix(params->GetFrameGravity(),
198         { frameRect.GetLeft(), frameRect.GetTop(), frameRect.GetWidth(), frameRect.GetHeight() },
199         params->GetBounds().GetWidth(), params->GetBounds().GetHeight(), mat)) {
200         canvas.ConcatMatrix(mat);
201     }
202     auto ctx = RSUniRenderThread::Instance().GetRSRenderThreadParams()->GetContext();
203     Flush(rect.GetWidth(), rect.GetHeight(), ctx, nodeId_,
204         *static_cast<RSPaintFilterCanvas*>(&canvas)); // getimage
205     if (image_ == nullptr) {
206         RS_LOGD("Failed to draw gpu image!");
207         return;
208     }
209 
210     auto samplingOptions = Drawing::SamplingOptions(Drawing::FilterMode::LINEAR, Drawing::MipmapMode::NONE);
211     Drawing::Paint paint;
212     paint.SetStyle(Drawing::Paint::PaintStyle::PAINT_FILL);
213     canvas.AttachPaint(paint);
214     canvas.DrawImage(*image_, 0.f, 0.f, samplingOptions);
215     canvas.DetachPaint();
216 }
217 
OnCapture(Drawing::Canvas & canvas)218 void RSCanvasDrawingRenderNodeDrawable::OnCapture(Drawing::Canvas& canvas)
219 {
220     if (RSRenderNodeDrawable::DealWithWhiteListNodes(canvas)) {
221         return;
222     }
223     OnDraw(canvas);
224 }
225 
CheckAndSetThreadIdx(uint32_t & threadIdx)226 void RSCanvasDrawingRenderNodeDrawable::CheckAndSetThreadIdx(uint32_t& threadIdx)
227 {
228     auto realTid = gettid();
229     if (realTid == RSUniRenderThread::Instance().GetTid()) {
230         threadIdx = UNI_RENDER_THREAD_INDEX;
231     } else {
232         for (auto& [idx, tid] : RSSubThreadManager::Instance()->GetReThreadIndexMap()) {
233             if (tid == realTid) {
234                 threadIdx = idx;
235                 break;
236             }
237         }
238     }
239 }
240 
CheckPostplaybackParamValid(NodeId nodeId,pid_t threadId)241 bool RSCanvasDrawingRenderNodeDrawable::CheckPostplaybackParamValid(NodeId nodeId, pid_t threadId)
242 {
243     if (!IsNeedDraw()) {
244         return false;
245     }
246 
247     if (!renderParams_) {
248         RS_LOGE("PostPlaybackInCorrespondThread NodeId[%{public}" PRIu64 "] renderParams null", nodeId);
249         return false;
250     }
251 
252     if (threadId != threadId_) {
253         RS_LOGE("PostPlaybackInCorrespondThread ThreadId Error NodeId[%{public}" PRIu64 "],"
254             "threadId[%{public}d], threadId_[%{public}d]", nodeId, threadId, threadId_.load());
255         return false;
256     }
257 
258     return true;
259 }
260 
PostPlaybackInCorrespondThread()261 void RSCanvasDrawingRenderNodeDrawable::PostPlaybackInCorrespondThread()
262 {
263     auto canvasDrawingPtr = shared_from_this();
264     pid_t threadId = threadId_;
265     RS_OPTIONAL_TRACE_NAME_FMT("post playback task node[%llu]", GetId());
266     auto task = [this, canvasDrawingPtr, threadId]() {
267         std::unique_lock<std::recursive_mutex> lock(drawableMutex_);
268         auto nodeId = GetId();
269         // default in unirenderthread
270         if (!CheckPostplaybackParamValid(nodeId, threadId)) {
271             return;
272         }
273 
274         RSRenderNodeSingleDrawableLocker singleLocker(this);
275         if (UNLIKELY(!singleLocker.IsLocked())) {
276             singleLocker.DrawableOnDrawMultiAccessEventReport(__func__);
277             RS_LOGE("RSCanvasDrawingRenderNodeDrawable::Postplayback node %{public}" PRIu64 " playback!!!", GetId());
278             if (RSSystemProperties::GetSingleDrawableLockerEnabled()) {
279                 return;
280             }
281         }
282 
283         if (renderParams_->GetCanvasDrawingSurfaceChanged()) {
284             ResetSurface();
285             RS_LOGI("PostPlaybackInCorrespondThread NodeId[%{public}" PRIu64 "] SurfaceChanged Reset Surface", nodeId);
286             renderParams_->SetCanvasDrawingSurfaceChanged(false);
287         }
288 
289         auto surfaceParams = renderParams_->GetCanvasDrawingSurfaceParams();
290         if (!surface_ || !canvas_) {
291             if (!ResetSurfaceforPlayback(surfaceParams.width, surfaceParams.height)) {
292                 RS_LOGE("PostPlaybackInCorrespondThread Reset Surface Error NodeId[%{public}" PRIu64
293                     "], width[%{public}d], height[%{public}d]", nodeId, surfaceParams.width, surfaceParams.height);
294                 return;
295             }
296 
297             uint32_t threadIdx = UNI_MAIN_THREAD_INDEX;
298             CheckAndSetThreadIdx(threadIdx);
299             auto clearFunc = [idx = threadIdx](std::shared_ptr<Drawing::Surface> surface) {
300                 // The second param is null, 0 is an invalid value.
301                 RSUniRenderUtil::ClearNodeCacheSurface(std::move(surface), nullptr, idx, 0);
302             };
303             SetSurfaceClearFunc({ threadIdx, clearFunc }, threadId);
304         }
305         RS_TRACE_NAME_FMT("PostPlaybackInCorrespondThread NodeId[%" PRIu64 "]", nodeId);
306         RS_LOGI_LIMIT("CanvasDrawing PostPlayback NodeId[%{public}" PRIu64 "] finish draw", nodeId);
307         auto rect = GetRenderParams()->GetBounds();
308         DrawContent(*canvas_, rect);
309         SetNeedDraw(false);
310         canvas_->Flush();
311     };
312     RSTaskDispatcher::GetInstance().PostTask(threadId, task, false);
313 }
314 
InitSurface(int width,int height,RSPaintFilterCanvas & canvas)315 bool RSCanvasDrawingRenderNodeDrawable::InitSurface(int width, int height, RSPaintFilterCanvas& canvas)
316 {
317 #if defined(RS_ENABLE_GL) || defined(RS_ENABLE_VK)
318     if (RSSystemProperties::GetGpuApiType() == GpuApiType::OPENGL) {
319         return InitSurfaceForGL(width, height, canvas);
320     }
321     if (RSSystemProperties::GetGpuApiType() == GpuApiType::VULKAN ||
322         RSSystemProperties::GetGpuApiType() == GpuApiType::DDGR) {
323         return InitSurfaceForVK(width, height, canvas);
324     }
325 #endif
326     return false;
327 }
328 
329 #if defined(RS_ENABLE_GL) || defined(RS_ENABLE_VK)
InitSurfaceForGL(int width,int height,RSPaintFilterCanvas & canvas)330 bool RSCanvasDrawingRenderNodeDrawable::InitSurfaceForGL(int width, int height, RSPaintFilterCanvas& canvas)
331 {
332     if (IsNeedResetSurface()) {
333         ClearPreSurface(surface_);
334         preThreadInfo_ = curThreadInfo_;
335         if (!ResetSurfaceForGL(width, height, canvas)) {
336             return false;
337         }
338     } else if ((isGpuSurface_) && (preThreadInfo_.first != curThreadInfo_.first)) {
339         if (!ResetSurfaceWithTexture(width, height, canvas)) {
340             return false;
341         }
342     }
343     if (!surface_) {
344         return false;
345     }
346     return true;
347 }
348 
InitSurfaceForVK(int width,int height,RSPaintFilterCanvas & canvas)349 bool RSCanvasDrawingRenderNodeDrawable::InitSurfaceForVK(int width, int height, RSPaintFilterCanvas& canvas)
350 {
351     if (IsNeedResetSurface()) {
352         ClearPreSurface(surface_);
353         preThreadInfo_ = curThreadInfo_;
354         if (!ResetSurfaceForVK(width, height, canvas)) {
355             return false;
356         }
357     } else if ((isGpuSurface_) && (preThreadInfo_.first != curThreadInfo_.first)) {
358         if (!ReuseBackendTexture(width, height, canvas)) {
359             return false;
360         }
361     }
362     if (!surface_) {
363         return false;
364     }
365     return true;
366 }
367 
FlushForGL(float width,float height,std::shared_ptr<RSContext> context,NodeId nodeId,RSPaintFilterCanvas & rscanvas)368 void RSCanvasDrawingRenderNodeDrawable::FlushForGL(float width, float height, std::shared_ptr<RSContext> context,
369     NodeId nodeId, RSPaintFilterCanvas& rscanvas)
370 {
371     if (!recordingCanvas_) {
372         if (rscanvas.GetParallelThreadIdx() != curThreadInfo_.first) {
373             if (!backendTexture_.IsValid()) {
374                 RS_LOGE("RSCanvasDrawingRenderNodeDrawable::Flush backendTexture_ is nullptr");
375                 return;
376             }
377             if (rscanvas.GetGPUContext() == nullptr) {
378                 RS_LOGE("RSCanvasDrawingRenderNodeDrawable::Flush GPU context is nullptr");
379                 return;
380             }
381             Drawing::TextureOrigin origin = GetTextureOrigin();
382             Drawing::BitmapFormat info = Drawing::BitmapFormat{ image_->GetColorType(), image_->GetAlphaType() };
383             SharedTextureContext* sharedContext = new SharedTextureContext(image_); // last image
384             image_ = std::make_shared<Drawing::Image>();
385             ReleaseCaptureImage();
386             bool ret = image_->BuildFromTexture(*rscanvas.GetGPUContext(), backendTexture_.GetTextureInfo(), origin,
387                 info, nullptr, SKResourceManager::DeleteSharedTextureContext, sharedContext);
388             if (!ret) {
389                 RS_LOGE("RSCanvasDrawingRenderNodeDrawable::Flush image BuildFromTexture failed");
390                 return;
391             }
392         } else {
393             image_ = surface_->GetImageSnapshot(); // planning: return image_
394             backendTexture_ = surface_->GetBackendTexture();
395             ReleaseCaptureImage();
396             if (!backendTexture_.IsValid()) {
397                 RS_LOGE("RSCanvasDrawingRenderNodeDrawable::Flush !backendTexture_.IsValid() %d", __LINE__);
398             }
399         }
400 
401         if (image_) {
402             SKResourceManager::Instance().HoldResource(image_);
403         }
404     } else {
405         auto cmds = recordingCanvas_->GetDrawCmdList();
406         if (cmds && !cmds->IsEmpty()) {
407             recordingCanvas_ = std::make_shared<ExtendRecordingCanvas>(width, height, false);
408             canvas_ = std::make_unique<RSPaintFilterCanvas>(recordingCanvas_.get());
409             ProcessCPURenderInBackgroundThread(cmds, context, nodeId);
410         }
411     }
412 }
413 
FlushForVK(float width,float height,std::shared_ptr<RSContext> context,NodeId nodeId,RSPaintFilterCanvas & rscanvas)414 void RSCanvasDrawingRenderNodeDrawable::FlushForVK(float width, float height, std::shared_ptr<RSContext> context,
415     NodeId nodeId, RSPaintFilterCanvas& rscanvas)
416 {
417     if (!recordingCanvas_) {
418         REAL_ALLOC_CONFIG_SET_STATUS(true);
419         image_ = surface_->GetImageSnapshot();
420         REAL_ALLOC_CONFIG_SET_STATUS(false);
421     } else {
422         auto cmds = recordingCanvas_->GetDrawCmdList();
423         if (cmds && !cmds->IsEmpty()) {
424             recordingCanvas_ = std::make_shared<ExtendRecordingCanvas>(width, height, false);
425             canvas_ = std::make_unique<RSPaintFilterCanvas>(recordingCanvas_.get());
426             ProcessCPURenderInBackgroundThread(cmds, context, nodeId);
427         }
428     }
429 }
430 #endif
431 
Flush(float width,float height,std::shared_ptr<RSContext> context,NodeId nodeId,RSPaintFilterCanvas & rscanvas)432 void RSCanvasDrawingRenderNodeDrawable::Flush(float width, float height, std::shared_ptr<RSContext> context,
433     NodeId nodeId, RSPaintFilterCanvas& rscanvas)
434 {
435 #if defined(RS_ENABLE_GL) || defined(RS_ENABLE_VK)
436     if (RSSystemProperties::GetGpuApiType() == GpuApiType::VULKAN ||
437         RSSystemProperties::GetGpuApiType() == GpuApiType::DDGR) {
438         FlushForVK(width, height, context, nodeId, rscanvas);
439     }
440     if (RSSystemProperties::GetGpuApiType() == GpuApiType::OPENGL) {
441         FlushForGL(width, height, context, nodeId, rscanvas);
442     }
443 #endif
444 }
445 
ProcessCPURenderInBackgroundThread(std::shared_ptr<Drawing::DrawCmdList> cmds,std::shared_ptr<RSContext> ctx,NodeId nodeId)446 void RSCanvasDrawingRenderNodeDrawable::ProcessCPURenderInBackgroundThread(std::shared_ptr<Drawing::DrawCmdList> cmds,
447     std::shared_ptr<RSContext> ctx, NodeId nodeId)
448 {
449     auto surface = surface_;
450     auto drawable = RSRenderNodeDrawableAdapter::GetDrawableById(nodeId);
451     RSBackgroundThread::Instance().PostTask([drawable, cmds, surface, ctx, nodeId]() {
452         if (!cmds || cmds->IsEmpty() || !surface || !ctx || !drawable) {
453             return;
454         }
455         Drawing::GPUResourceTag::SetCurrentNodeId(nodeId);
456         auto canvasDrawingDrawable = std::static_pointer_cast<DrawableV2::RSCanvasDrawingRenderNodeDrawable>(drawable);
457         std::shared_ptr<Drawing::Canvas> canvas = nullptr;
458         {
459             std::unique_lock<std::recursive_mutex> lock(canvasDrawingDrawable->drawableMutex_);
460             if (surface != canvasDrawingDrawable->surface_) {
461                 return;
462             }
463             canvas = surface->GetCanvas();
464         }
465         if (canvas == nullptr) {
466             RS_LOGE("RSCanvasDrawingRenderNodeDrawable::ProcessCPURenderInBackgroundThread get canvas is null");
467             return;
468         }
469         RS_LOGI("RSCanvasDrawingRenderNodeDrawable::ProcessCPURenderInBackgroundThread surface width[%{public}d],"
470             " height[%{public}d]", surface->GetImageInfo().GetWidth(), surface->GetImageInfo().GetHeight());
471         cmds->Playback(*canvas);
472         auto image = surface->GetImageSnapshot(); // planning: adapt multithread
473         if (image) {
474             SKResourceManager::Instance().HoldResource(image);
475         }
476         {
477             std::unique_lock<std::recursive_mutex> lock(canvasDrawingDrawable->drawableMutex_);
478             canvasDrawingDrawable->image_ = image;
479         }
480         if (UNLIKELY(!ctx)) {
481             return;
482         }
483         RSMainThread::Instance()->PostTask([ctx, nodeId]() {
484             if (auto node = ctx->GetNodeMap().GetRenderNode<RSCanvasDrawingRenderNode>(nodeId)) {
485                 ROSEN_LOGD("Node id %{public}" PRIu64 " set dirty, process in RSMainThread", nodeId);
486                 node->SetDirty();
487                 ctx->RequestVsync();
488             }
489         });
490     });
491 }
492 
ResetSurface()493 void RSCanvasDrawingRenderNodeDrawable::ResetSurface()
494 {
495     RS_LOGI("RSCanvasDrawingRenderNodeDrawable::ResetSurface NodeId[%{public}" PRIu64 "] ResetSurface", GetId());
496     if (surface_ && surface_->GetImageInfo().GetWidth() > EDGE_WIDTH_LIMIT) {
497         RS_LOGE("RSCanvasDrawingRenderNodeDrawable::ResetSurface id:%{public}" PRIu64 "]", nodeId_);
498     }
499     if (preThreadInfo_.second && surface_) {
500         preThreadInfo_.second(std::move(surface_));
501     }
502     surface_ = nullptr;
503     recordingCanvas_ = nullptr;
504     image_ = nullptr;
505     canvas_ = nullptr;
506 #if (defined(RS_ENABLE_GL) || defined(RS_ENABLE_VK))
507     backendTexture_ = {};
508     if (RSSystemProperties::GetGpuApiType() == GpuApiType::VULKAN ||
509         RSSystemProperties::GetGpuApiType() == GpuApiType::DDGR) {
510         vulkanCleanupHelper_ = nullptr;
511     }
512 #endif
513 }
514 
515 // use in IPC thread
GetBitmap(Drawing::GPUContext * grContext)516 Drawing::Bitmap RSCanvasDrawingRenderNodeDrawable::GetBitmap(Drawing::GPUContext* grContext)
517 {
518     Drawing::Bitmap bitmap;
519     std::unique_lock<std::recursive_mutex> lock(drawableMutex_);
520     // Judge valid of backendTexture_ by checking the image_.
521     if (!image_) {
522         RS_LOGE("Failed to get bitmap, image is null!");
523         return bitmap;
524     }
525     if (!grContext) {
526         RS_LOGE("Failed to get bitmap, grContext is null!");
527         return bitmap;
528     }
529 #if (defined(RS_ENABLE_GL) || defined(RS_ENABLE_VK))
530     Drawing::GPUResourceTag::SetCurrentNodeId(GetId());
531     Drawing::TextureOrigin origin = GetTextureOrigin();
532     Drawing::BitmapFormat info = Drawing::BitmapFormat{ image_->GetColorType(), image_->GetAlphaType() };
533     auto image = std::make_shared<Drawing::Image>();
534     bool ret = image->BuildFromTexture(*grContext, backendTexture_.GetTextureInfo(), origin, info, nullptr);
535     if (!ret) {
536         RS_LOGE("RSCanvasDrawingRenderNodeDrawable::GetBitmap image BuildFromTexture failed");
537         return bitmap;
538     }
539     if (!image->AsLegacyBitmap(bitmap)) {
540         RS_LOGE("Failed to get bitmap, asLegacyBitmap failed");
541     }
542 #endif
543     return bitmap;
544 }
545 
WriteSkImageToPixelmap(std::shared_ptr<Drawing::Image> image,Drawing::ImageInfo info,std::shared_ptr<Media::PixelMap> pixelmap,const Drawing::Rect * rect)546 static bool WriteSkImageToPixelmap(std::shared_ptr<Drawing::Image> image, Drawing::ImageInfo info,
547     std::shared_ptr<Media::PixelMap> pixelmap, const Drawing::Rect* rect)
548 {
549     if (image == nullptr || pixelmap == nullptr || rect == nullptr) {
550         return false;
551     }
552     return image->ReadPixels(
553         info, pixelmap->GetWritablePixels(), pixelmap->GetRowStride(),
554         rect->GetLeft(), rect->GetTop());
555 }
556 
557 // use in IPC thread
GetPixelmap(const std::shared_ptr<Media::PixelMap> pixelmap,const Drawing::Rect * rect,const uint64_t tid,std::shared_ptr<Drawing::DrawCmdList> drawCmdList)558 bool RSCanvasDrawingRenderNodeDrawable::GetPixelmap(const std::shared_ptr<Media::PixelMap> pixelmap,
559     const Drawing::Rect* rect, const uint64_t tid, std::shared_ptr<Drawing::DrawCmdList> drawCmdList)
560 {
561     std::unique_lock<std::recursive_mutex> lock(drawableMutex_);
562 
563     if (!pixelmap || !rect) {
564         RS_LOGE("RSCanvasDrawingRenderNodeDrawable::GetPixelmap: pixelmap is nullptr");
565         return false;
566     }
567     if (!canvas_ || !image_ || !surface_) {
568         RS_LOGE("RSCanvasDrawingRenderNodeDrawable::GetPixelmap: canvas/image/surface is nullptr");
569         return false;
570     }
571     std::shared_ptr<Drawing::Image> image;
572 #if (defined(RS_ENABLE_GL) || defined(RS_ENABLE_VK))
573     std::shared_ptr<Drawing::GPUContext> grContext;
574     Drawing::GPUResourceTag::SetCurrentNodeId(GetId());
575     if (!GetCurrentContextAndImage(grContext, image, tid)) {
576         RS_LOGE("RSCanvasDrawingRenderNodeDrawable::GetPixelmap: GetCurrentContextAndImage failed");
577         return false;
578     }
579 #endif
580 
581     if (image == nullptr) {
582         RS_LOGE("RSCanvasDrawingRenderNodeDrawable::GetPixelmap: image is nullptr");
583         return false;
584     }
585 
586     Drawing::ImageInfo info = Drawing::ImageInfo { pixelmap->GetWidth(), pixelmap->GetHeight(),
587         Drawing::COLORTYPE_RGBA_8888, Drawing::ALPHATYPE_PREMUL };
588     if (!drawCmdList) {
589         if (!WriteSkImageToPixelmap(image, info, pixelmap, rect)) {
590             RS_LOGE("RSCanvasDrawingRenderNodeDrawable::GetPixelmap: readPixels failed");
591             return false;
592         }
593         return true;
594     }
595     std::shared_ptr<Drawing::Surface> surface;
596     std::unique_ptr<RSPaintFilterCanvas> canvas;
597 #if (defined(RS_ENABLE_GL) || defined(RS_ENABLE_VK))
598     if (grContext == nullptr) {
599         if (!WriteSkImageToPixelmap(image, info, pixelmap, rect)) {
600             RS_LOGE("RSCanvasDrawingRenderNodeDrawable::GetPixelmap: readPixels failed");
601         }
602         return false;
603     } else {
604         Drawing::ImageInfo newInfo = Drawing::ImageInfo{ image->GetWidth(), image->GetHeight(),
605             Drawing::COLORTYPE_RGBA_8888, Drawing::ALPHATYPE_PREMUL };
606         surface = Drawing::Surface::MakeRenderTarget(grContext.get(), false, newInfo);
607         if (!surface) {
608             if (!WriteSkImageToPixelmap(image, info, pixelmap, rect)) {
609                 RS_LOGE("RSCanvasDrawingRenderNodeDrawable::GetPixelmap: readPixels failed");
610             }
611             return false;
612         }
613         canvas = std::make_unique<RSPaintFilterCanvas>(surface.get());
614     }
615 #else
616     if (!WriteSkImageToPixelmap(image, info, pixelmap, rect)) {
617         RS_LOGE("RSCanvasDrawingRenderNodeDrawable::GetPixelmap: readPixels failed");
618     }
619     return false;
620 #endif
621     canvas->DrawImage(*image, 0, 0, Drawing::SamplingOptions());
622     drawCmdList->Playback(*canvas, rect);
623     canvas->Flush();
624     auto pixelmapImage = surface->GetImageSnapshot();
625     if (!WriteSkImageToPixelmap(pixelmapImage, info, pixelmap, rect)) {
626         RS_LOGE("RSCanvasDrawingRenderNodeDrawable::GetPixelmap: readPixels failed");
627         return false;
628     }
629     return true;
630 }
631 
IsNeedResetSurface() const632 bool RSCanvasDrawingRenderNodeDrawable::IsNeedResetSurface() const
633 {
634     return !surface_ || !surface_->GetCanvas();
635 }
636 
ReleaseCaptureImage()637 void RSCanvasDrawingRenderNodeDrawable::ReleaseCaptureImage()
638 {
639     RSOffscreenRenderThread::Instance().PostTask([image = captureImage_]() mutable { image = nullptr; });
640     captureImage_ = nullptr;
641 }
642 
DrawCaptureImage(RSPaintFilterCanvas & canvas)643 void RSCanvasDrawingRenderNodeDrawable::DrawCaptureImage(RSPaintFilterCanvas& canvas)
644 {
645 #if (defined(RS_ENABLE_GL) || defined(RS_ENABLE_VK))
646     if (!image_) {
647         OnDraw(canvas);
648         return;
649     }
650     if (image_ && !image_->IsTextureBacked()) {
651         canvas.DrawImage(*image_, 0, 0, Drawing::SamplingOptions());
652         return;
653     }
654 
655     if (RSSystemProperties::GetGpuApiType() == GpuApiType::OPENGL) {
656         return;
657     }
658 
659     if (!backendTexture_.IsValid()) {
660         return;
661     }
662     if (canvas.GetGPUContext() == nullptr) {
663         RS_LOGE("RSCanvasDrawingRenderNodeDrawable::DrawCaptureImage canvas.GetGPUContext is nullptr");
664         return;
665     }
666     if (captureImage_ && captureImage_->IsValid(canvas.GetGPUContext().get())) {
667         canvas.DrawImage(*captureImage_, 0, 0, Drawing::SamplingOptions());
668         return;
669     }
670     Drawing::TextureOrigin origin = GetTextureOrigin();
671     Drawing::BitmapFormat info = Drawing::BitmapFormat{ image_->GetColorType(), image_->GetAlphaType() };
672     SharedTextureContext* sharedContext = new SharedTextureContext(image_);
673     captureImage_ = std::make_shared<Drawing::Image>();
674     bool ret = captureImage_->BuildFromTexture(*canvas.GetGPUContext(), backendTexture_.GetTextureInfo(), origin, info,
675         nullptr, SKResourceManager::DeleteSharedTextureContext, sharedContext);
676     if (!ret) {
677         RS_LOGE("RSCanvasDrawingRenderNodeDrawable::DrawCaptureImage BuildFromTexture failed");
678         return;
679     }
680     canvas.DrawImage(*captureImage_, 0, 0, Drawing::SamplingOptions());
681 #endif
682 }
683 
684 #ifdef RS_ENABLE_VK
ReleaseSurfaceVK(int width,int height)685 bool RSCanvasDrawingRenderNodeDrawable::ReleaseSurfaceVK(int width, int height)
686 {
687     if (!backendTexture_.IsValid() || !backendTexture_.GetTextureInfo().GetVKTextureInfo()) {
688         backendTexture_ = NativeBufferUtils::MakeBackendTexture(width, height, ExtractPid(nodeId_));
689         if (!backendTexture_.IsValid()) {
690             surface_ = nullptr;
691             recordingCanvas_ = nullptr;
692             image_ = nullptr;
693             canvas_ = nullptr;
694             backendTexture_ = {};
695             if (RSSystemProperties::GetGpuApiType() == GpuApiType::VULKAN ||
696                 RSSystemProperties::GetGpuApiType() == GpuApiType::DDGR) {
697                 vulkanCleanupHelper_ = nullptr;
698             }
699             RS_LOGE("RSCanvasDrawingRenderNodeDrawable::ResetSurfaceForVK size too big [%{public}d, %{public}d] failed",
700                 width, height);
701             return false;
702         }
703     }
704     return true;
705 }
706 #endif
707 
ResetSurfaceForVK(int width,int height,RSPaintFilterCanvas & canvas)708 bool RSCanvasDrawingRenderNodeDrawable::ResetSurfaceForVK(int width, int height, RSPaintFilterCanvas& canvas)
709 {
710     const auto& params = GetRenderParams();
711     GraphicColorGamut colorSpace = GraphicColorGamut::GRAPHIC_COLOR_GAMUT_SRGB;
712     if (params) {
713         colorSpace = params->GetCanvasDrawingSurfaceParams().colorSpace;
714     }
715     auto drawingColorSpace = RSBaseRenderEngine::ConvertColorGamutToDrawingColorSpace(colorSpace);
716     Drawing::ImageInfo info = Drawing::ImageInfo { width, height, Drawing::COLORTYPE_RGBA_8888,
717         Drawing::ALPHATYPE_PREMUL, drawingColorSpace };
718 
719     bool isNewCreate = false;
720 #ifdef RS_ENABLE_VK
721     auto gpuContext = canvas.GetRecordingState() ? nullptr : canvas.GetGPUContext();
722     isGpuSurface_ = true;
723     if (gpuContext == nullptr) {
724         RS_LOGE("RSCanvasDrawingRenderNodeDrawable::ResetSurface: gpuContext is nullptr");
725         isGpuSurface_ = false;
726         surface_ = Drawing::Surface::MakeRaster(info);
727     } else {
728         if (!ReleaseSurfaceVK(width, height)) {
729             return false;
730         }
731         auto vkTextureInfo = backendTexture_.GetTextureInfo().GetVKTextureInfo();
732         if (vulkanCleanupHelper_ == nullptr) {
733             vulkanCleanupHelper_ = new NativeBufferUtils::VulkanCleanupHelper(RsVulkanContext::GetSingleton(),
734                 vkTextureInfo->vkImage, vkTextureInfo->vkAlloc.memory, vkTextureInfo->vkAlloc.statName);
735             isNewCreate = true;
736         }
737         REAL_ALLOC_CONFIG_SET_STATUS(true);
738         surface_ = Drawing::Surface::MakeFromBackendTexture(gpuContext.get(), backendTexture_.GetTextureInfo(),
739             Drawing::TextureOrigin::TOP_LEFT, 1, Drawing::ColorType::COLORTYPE_RGBA_8888, drawingColorSpace,
740             NativeBufferUtils::DeleteVkImage, isNewCreate ? vulkanCleanupHelper_ : vulkanCleanupHelper_->Ref());
741         REAL_ALLOC_CONFIG_SET_STATUS(false);
742         if (!surface_) {
743             isGpuSurface_ = false;
744             surface_ = Drawing::Surface::MakeRaster(info);
745             if (!surface_) {
746                 RS_LOGE("RSCanvasDrawingRenderNodeDrawable::ResetSurface surface is nullptr");
747                 ResetSurface();
748                 return false;
749             }
750             recordingCanvas_ = std::make_shared<ExtendRecordingCanvas>(width, height, false);
751             canvas_ = std::make_unique<RSPaintFilterCanvas>(recordingCanvas_.get());
752             return true;
753         }
754     }
755 #else
756     surface_ = Drawing::Surface::MakeRaster(info);
757 #endif
758     if (!surface_) {
759         RS_LOGE("RSCanvasDrawingRenderNodeDrawable::ResetSurface surface is nullptr");
760         ResetSurface();
761         return false;
762     }
763     recordingCanvas_ = nullptr;
764     canvas_ = std::make_shared<RSPaintFilterCanvas>(surface_.get());
765     if (isNewCreate) {
766         canvas_->Clear(Drawing::Color::COLOR_TRANSPARENT);
767     }
768     return true;
769 }
770 
ResetSurfaceForGL(int width,int height,RSPaintFilterCanvas & canvas)771 bool RSCanvasDrawingRenderNodeDrawable::ResetSurfaceForGL(int width, int height, RSPaintFilterCanvas& canvas)
772 {
773     Drawing::ImageInfo info =
774         Drawing::ImageInfo { width, height, Drawing::COLORTYPE_RGBA_8888, Drawing::ALPHATYPE_PREMUL };
775 
776 #if (defined(RS_ENABLE_GL) || defined(RS_ENABLE_VK))
777     auto gpuContext = canvas.GetRecordingState() ? nullptr : canvas.GetGPUContext();
778     isGpuSurface_ = true;
779     if (gpuContext == nullptr) {
780         RS_LOGE("RSCanvasDrawingRenderNodeDrawable::ResetSurface: gpuContext is nullptr");
781         isGpuSurface_ = false;
782         surface_ = Drawing::Surface::MakeRaster(info);
783     } else {
784         surface_ = Drawing::Surface::MakeRenderTarget(gpuContext.get(), false, info);
785         if (!surface_) {
786             isGpuSurface_ = false;
787             surface_ = Drawing::Surface::MakeRaster(info);
788             if (!surface_) {
789                 RS_LOGE("RSCanvasDrawingRenderNodeDrawable::ResetSurface surface is nullptr");
790                 return false;
791             }
792             recordingCanvas_ = std::make_shared<ExtendRecordingCanvas>(width, height, false);
793             canvas_ = std::make_unique<RSPaintFilterCanvas>(recordingCanvas_.get());
794             return true;
795         }
796     }
797 #else
798     surface_ = Drawing::Surface::MakeRaster(info);
799 #endif
800     if (!surface_) {
801         RS_LOGE("RSCanvasDrawingRenderNodeDrawable::ResetSurface surface is nullptr");
802         return false;
803     }
804     recordingCanvas_ = nullptr;
805     canvas_ = std::make_shared<RSPaintFilterCanvas>(surface_.get());
806     return true;
807 }
808 
GetCurrentContext(std::shared_ptr<Drawing::GPUContext> & grContext)809 bool RSCanvasDrawingRenderNodeDrawable::GetCurrentContext(std::shared_ptr<Drawing::GPUContext>& grContext)
810 {
811     auto realTid = gettid();
812     if (realTid == RSUniRenderThread::Instance().GetTid()) {
813         grContext = RSUniRenderThread::Instance().GetRenderEngine()->GetRenderContext()->GetSharedDrGPUContext();
814         if (!grContext) {
815             RS_LOGE("RSCanvasDrawingRenderNodeDrawable::GetCurrentContext UniRenderThread get grGrContext failed");
816             return false;
817         }
818     } else {
819         grContext = RSSubThreadManager::Instance()->GetGrContextFromSubThread(realTid);
820         if (!grContext) {
821             RS_LOGE("RSCanvasDrawingRenderNodeDrawable::GetCurrentContext SubThread get grGrContext failed");
822             return false;
823         }
824     }
825     return true;
826 }
827 
GpuContextResetGL(int width,int height,std::shared_ptr<Drawing::GPUContext> & gpuContext)828 bool RSCanvasDrawingRenderNodeDrawable::GpuContextResetGL(
829     int width, int height, std::shared_ptr<Drawing::GPUContext>& gpuContext)
830 {
831     Drawing::ImageInfo info =
832         Drawing::ImageInfo { width, height, Drawing::COLORTYPE_RGBA_8888, Drawing::ALPHATYPE_PREMUL };
833 #if (defined(RS_ENABLE_GL) || defined(RS_ENABLE_VK))
834     surface_ = Drawing::Surface::MakeRenderTarget(gpuContext.get(), false, info);
835     if (!surface_) {
836         isGpuSurface_ = false;
837         surface_ = Drawing::Surface::MakeRaster(info);
838         if (!surface_) {
839             RS_LOGE("RSCanvasDrawingRenderNodeDrawable::GL Reset surface is nullptr");
840             return false;
841         }
842         recordingCanvas_ = std::make_shared<ExtendRecordingCanvas>(width, height, false);
843         canvas_ = std::make_unique<RSPaintFilterCanvas>(recordingCanvas_.get());
844         return true;
845     }
846 #else
847     surface_ = Drawing::Surface::MakeRaster(info);
848 #endif
849     return true;
850 }
851 
GpuContextResetVK(int width,int height,std::shared_ptr<Drawing::GPUContext> & gpuContext)852 bool RSCanvasDrawingRenderNodeDrawable::GpuContextResetVK(
853     int width, int height, std::shared_ptr<Drawing::GPUContext>& gpuContext)
854 {
855     Drawing::ImageInfo info =
856         Drawing::ImageInfo { width, height, Drawing::COLORTYPE_RGBA_8888, Drawing::ALPHATYPE_PREMUL };
857 
858     bool isNewCreate = false;
859 #if defined(RS_ENABLE_VK)
860     if (!ReleaseSurfaceVK(width, height)) {
861         return false;
862     }
863     auto vkTextureInfo = backendTexture_.GetTextureInfo().GetVKTextureInfo();
864     if (vulkanCleanupHelper_ == nullptr) {
865         vulkanCleanupHelper_ = new NativeBufferUtils::VulkanCleanupHelper(RsVulkanContext::GetSingleton(),
866             vkTextureInfo->vkImage, vkTextureInfo->vkAlloc.memory, vkTextureInfo->vkAlloc.statName);
867         isNewCreate = true;
868     }
869     REAL_ALLOC_CONFIG_SET_STATUS(true);
870     surface_ = Drawing::Surface::MakeFromBackendTexture(gpuContext.get(), backendTexture_.GetTextureInfo(),
871         Drawing::TextureOrigin::TOP_LEFT, 1, Drawing::ColorType::COLORTYPE_RGBA_8888, nullptr,
872         NativeBufferUtils::DeleteVkImage, isNewCreate ? vulkanCleanupHelper_ : vulkanCleanupHelper_->Ref());
873     REAL_ALLOC_CONFIG_SET_STATUS(false);
874     if (!surface_) {
875         isGpuSurface_ = false;
876         surface_ = Drawing::Surface::MakeRaster(info);
877         if (!surface_) {
878             RS_LOGE("RSCanvasDrawingRenderNodeDrawable::VK Reset surface is nullptr, nodeId[%{public}" PRIu64 "]",
879                 GetId());
880             ResetSurface();
881             return false;
882         }
883         recordingCanvas_ = std::make_shared<ExtendRecordingCanvas>(width, height, false);
884         canvas_ = std::make_unique<RSPaintFilterCanvas>(recordingCanvas_.get());
885         return true;
886     }
887     return true;
888 #else
889     surface_ = Drawing::Surface::MakeRaster(info);
890 #endif
891     return true;
892 }
893 
ResetSurfaceforPlayback(int width,int height)894 bool RSCanvasDrawingRenderNodeDrawable::ResetSurfaceforPlayback(int width, int height)
895 {
896     Drawing::ImageInfo info =
897         Drawing::ImageInfo { width, height, Drawing::COLORTYPE_RGBA_8888, Drawing::ALPHATYPE_PREMUL };
898     RS_LOGI("RSCanvasDrawingRenderNodeDrawable::ResetSurfaceforPlayback NodeId[%{public}" PRIu64 "]", GetId());
899     std::shared_ptr<Drawing::GPUContext> gpuContext;
900     if (canvas_ == nullptr) {
901         if (!GetCurrentContext(gpuContext)) {
902             RS_LOGE("ResetSurfaceforPlayback canvas null, getContext Failed");
903             return false;
904         }
905     } else {
906         gpuContext = canvas_->GetGPUContext();
907     }
908 
909     isGpuSurface_ = true;
910     if (gpuContext == nullptr) {
911         isGpuSurface_ = false;
912         surface_ = Drawing::Surface::MakeRaster(info);
913     } else {
914         if (RSSystemProperties::GetGpuApiType() == GpuApiType::OPENGL) {
915             if (!GpuContextResetGL(width, height, gpuContext)) {
916                 return false;
917             }
918             if (canvas_) {
919                 return true;
920             }
921         }
922         if (RSSystemProperties::GetGpuApiType() == GpuApiType::VULKAN ||
923             RSSystemProperties::GetGpuApiType() == GpuApiType::DDGR) {
924             if (!GpuContextResetVK(width, height, gpuContext)) {
925                 return false;
926             }
927             if (canvas_) {
928                 return true;
929             }
930         }
931     }
932 
933     if (!surface_) {
934         RS_LOGE("RSCanvasDrawingRenderNodeDrawable::ResetSurfaceforPlayback surface is nullptr");
935         return false;
936     }
937     recordingCanvas_ = nullptr;
938     canvas_ = std::make_shared<RSPaintFilterCanvas>(surface_.get());
939     canvas_->Clear(Drawing::Color::COLOR_TRANSPARENT);
940     return true;
941 }
942 
943 #if (defined(RS_ENABLE_GL) || defined(RS_ENABLE_VK))
ClearPreSurface(std::shared_ptr<Drawing::Surface> & preSurface)944 inline void RSCanvasDrawingRenderNodeDrawable::ClearPreSurface(std::shared_ptr<Drawing::Surface>& preSurface)
945 {
946     if (preThreadInfo_.second && preSurface) {
947         preThreadInfo_.second(std::move(preSurface));
948     }
949 }
950 
ReuseBackendTexture(int width,int height,RSPaintFilterCanvas & canvas)951 bool RSCanvasDrawingRenderNodeDrawable::ReuseBackendTexture(int width, int height, RSPaintFilterCanvas& canvas)
952 {
953     auto preMatrix = canvas_->GetTotalMatrix();
954     auto preDeviceClipBounds = canvas_->GetDeviceClipBounds();
955     auto preSaveCount = canvas_->GetSaveCount();
956     auto preSurface = surface_;
957     if (!ResetSurfaceForVK(width, height, canvas)) {
958         ClearPreSurface(preSurface);
959         return false;
960     }
961     if (preSaveCount > 1) {
962         canvas_->Save();
963     }
964     canvas_->ClipIRect(preDeviceClipBounds);
965     canvas_->SetMatrix(preMatrix);
966     ClearPreSurface(preSurface);
967     preThreadInfo_ = curThreadInfo_;
968     ReleaseCaptureImage();
969     return true;
970 }
971 
GetCurrentContextAndImage(std::shared_ptr<Drawing::GPUContext> & grContext,std::shared_ptr<Drawing::Image> & image,const uint64_t tid)972 bool RSCanvasDrawingRenderNodeDrawable::GetCurrentContextAndImage(std::shared_ptr<Drawing::GPUContext>& grContext,
973     std::shared_ptr<Drawing::Image>& image, const uint64_t tid)
974 {
975     if (tid == preThreadInfo_.first) {
976         grContext = canvas_->GetGPUContext();
977         image = image_;
978     } else {
979         auto realTid = gettid();
980         if (realTid == RSUniRenderThread::Instance().GetTid()) {
981             grContext = RSUniRenderThread::Instance().GetRenderEngine()->GetRenderContext()->GetSharedDrGPUContext();
982         } else {
983             if (!RSSubThreadManager::Instance()->GetGrContextFromSubThread(realTid)) {
984                 RS_LOGE("RSCanvasDrawingRenderNodeDrawable::GetCurrentContextAndImage get grGrContext failed");
985                 return false;
986             }
987             grContext = RSSubThreadManager::Instance()->GetGrContextFromSubThread(realTid);
988         }
989 
990         if (!grContext || !backendTexture_.IsValid()) {
991             return false;
992         }
993         Drawing::TextureOrigin origin = GetTextureOrigin();
994         Drawing::BitmapFormat info = Drawing::BitmapFormat{ image_->GetColorType(), image_->GetAlphaType() };
995         image = std::make_shared<Drawing::Image>();
996         bool ret = image->BuildFromTexture(*grContext, backendTexture_.GetTextureInfo(), origin, info, nullptr);
997         if (!ret) {
998             RS_LOGE("RSCanvasDrawingRenderNodeDrawable::GetCurrentContextAndImage BuildFromTexture failed");
999             return false;
1000         }
1001     }
1002     return true;
1003 }
1004 
ResetSurfaceWithTexture(int width,int height,RSPaintFilterCanvas & canvas)1005 bool RSCanvasDrawingRenderNodeDrawable::ResetSurfaceWithTexture(int width, int height, RSPaintFilterCanvas& canvas)
1006 {
1007     if (width > EDGE_WIDTH_LIMIT) {
1008         RS_LOGI("RSCanvasDrawingRenderNodeDrawable::ResetSurfaceWithTexture id:%{public}" PRIu64 " "
1009              "width:%{public}d height:%{public}d ", nodeId_, width, height);
1010     }
1011     auto preMatrix = canvas_->GetTotalMatrix();
1012     auto preDeviceClipBounds = canvas_->GetDeviceClipBounds();
1013     auto preSaveCount = canvas_->GetSaveCount();
1014     auto preSurface = surface_;
1015     if (!ResetSurfaceForGL(width, height, canvas)) {
1016         ClearPreSurface(preSurface);
1017         return false;
1018     }
1019     if (!backendTexture_.IsValid()) {
1020         RS_LOGE("RSCanvasDrawingRenderNodeDrawable::ResetSurfaceWithTexture backendTexture_ is nullptr");
1021         ClearPreSurface(preSurface);
1022         return false;
1023     }
1024     if (canvas.GetGPUContext() == nullptr) {
1025         RS_LOGE("RSCanvasDrawingRenderNodeDrawable::ResetSurfaceWithTexture GPU context is nullptr");
1026         ClearPreSurface(preSurface);
1027         return false;
1028     }
1029 
1030     Drawing::TextureOrigin origin = GetTextureOrigin();
1031     Drawing::BitmapFormat bitmapFormat = { image_->GetColorType(), image_->GetAlphaType() };
1032     SharedTextureContext* sharedContext = new SharedTextureContext(image_); // will move image
1033     auto preImageInNewContext = std::make_shared<Drawing::Image>();
1034     if (!preImageInNewContext->BuildFromTexture(*canvas.GetGPUContext(), backendTexture_.GetTextureInfo(),
1035         origin, bitmapFormat, nullptr, SKResourceManager::DeleteSharedTextureContext, sharedContext)) {
1036         RS_LOGE("RSCanvasDrawingRenderNodeDrawable::ResetSurfaceWithTexture preImageInNewContext is nullptr");
1037         ClearPreSurface(preSurface);
1038         return false;
1039     }
1040     if (RSSystemProperties::GetRecordingEnabled()) {
1041         if (preImageInNewContext->IsTextureBacked()) {
1042             RS_LOGI("RSCanvasDrawingRenderNodeDrawable::ResetSurfaceWithTexture preImageInNewContext "
1043                 "from texture to raster image");
1044             preImageInNewContext = preImageInNewContext->MakeRasterImage();
1045         }
1046     }
1047     canvas_->DrawImage(*preImageInNewContext, 0.f, 0.f, Drawing::SamplingOptions());
1048     if (preSaveCount > 1) {
1049         canvas_->Save();
1050     }
1051     canvas_->ClipIRect(preDeviceClipBounds);
1052     canvas_->SetMatrix(preMatrix);
1053     canvas_->Flush();
1054     backendTexture_ = surface_->GetBackendTexture();
1055     if (!backendTexture_.IsValid()) {
1056         RS_LOGE("RSCanvasDrawingRenderNodeDrawable::ResetSurfaceWithTexture backendTexture_ generate invalid");
1057     }
1058     image_ = preImageInNewContext;
1059     ReleaseCaptureImage();
1060     ClearPreSurface(preSurface);
1061     preThreadInfo_ = curThreadInfo_;
1062     return true;
1063 }
1064 #endif
1065 
GetTextureOrigin()1066 Drawing::TextureOrigin RSCanvasDrawingRenderNodeDrawable::GetTextureOrigin()
1067 {
1068     if (RSSystemProperties::GetGpuApiType() == GpuApiType::OPENGL) {
1069         return Drawing::TextureOrigin::BOTTOM_LEFT;
1070     }
1071     return Drawing::TextureOrigin::TOP_LEFT;
1072 }
1073 
DrawRegionForDfx(Drawing::Canvas & canvas,const Drawing::Rect & bounds)1074 void RSCanvasDrawingRenderNodeDrawable::DrawRegionForDfx(Drawing::Canvas& canvas, const Drawing::Rect& bounds)
1075 {
1076     if (!RSSystemParameters::GetCanvasDrawingNodeRegionEnabled()) {
1077         return;
1078     }
1079     Drawing::Pen pen;
1080     pen.SetWidth(DRAW_REGION_FOR_DFX_BORDER);
1081     pen.SetColor(Drawing::Color::COLOR_RED);
1082     canvas.AttachPen(pen);
1083     canvas.DrawRect(Drawing::Rect(0, 0, bounds.GetWidth(), bounds.GetHeight()));
1084     canvas.DetachPen();
1085 }
1086 
1087 } // namespace OHOS::Rosen::DrawableV2
1088