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