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