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 "pipeline/rs_surface_capture_task_parallel.h"
17 
18 #include <memory>
19 #include <sys/mman.h>
20 
21 #include "draw/surface.h"
22 #include "draw/color.h"
23 #include "rs_trace.h"
24 
25 #include "common/rs_background_thread.h"
26 #include "common/rs_obj_abs_geometry.h"
27 #include "memory/rs_tag_tracker.h"
28 #include "params/rs_surface_render_params.h"
29 #include "pipeline/rs_base_render_node.h"
30 #include "pipeline/rs_display_render_node.h"
31 #include "pipeline/rs_main_thread.h"
32 #include "pipeline/rs_paint_filter_canvas.h"
33 #include "pipeline/rs_render_service_connection.h"
34 #include "pipeline/rs_surface_render_node.h"
35 #include "pipeline/rs_uifirst_manager.h"
36 #include "pipeline/rs_uni_render_judgement.h"
37 #include "pipeline/rs_uni_render_util.h"
38 #include "platform/common/rs_log.h"
39 #include "platform/drawing/rs_surface.h"
40 #include "render/rs_drawing_filter.h"
41 #include "render/rs_skia_filter.h"
42 #include "rs_base_render_engine.h"
43 #include "screen_manager/rs_screen_manager.h"
44 #include "screen_manager/rs_screen_mode_info.h"
45 
46 namespace OHOS {
47 namespace Rosen {
48 namespace {
DrawCapturedImg(Drawing::Image & image,Drawing::Surface & surface,const Drawing::BackendTexture & backendTexture,Drawing::TextureOrigin & textureOrigin,Drawing::BitmapFormat & bitmapFormat)49 inline void DrawCapturedImg(Drawing::Image& image,
50     Drawing::Surface& surface, const Drawing::BackendTexture& backendTexture,
51     Drawing::TextureOrigin& textureOrigin, Drawing::BitmapFormat& bitmapFormat)
52 {
53     RSPaintFilterCanvas canvas(&surface);
54     auto gpuContext = canvas.GetGPUContext();
55     if (gpuContext == nullptr) {
56         RS_LOGE("DrawCapturedImg failed: gpuContext is nullptr");
57         return;
58     }
59     auto colorSpace = surface.GetImageInfo().GetColorSpace();
60     image.BuildFromTexture(*gpuContext, backendTexture.GetTextureInfo(),
61         textureOrigin, bitmapFormat, colorSpace);
62     canvas.DrawImage(image, 0.f, 0.f, Drawing::SamplingOptions());
63     surface.FlushAndSubmit(true);
64 }
65 }
66 
CheckModifiers(NodeId id,bool useCurWindow)67 void RSSurfaceCaptureTaskParallel::CheckModifiers(NodeId id, bool useCurWindow)
68 {
69     RS_TRACE_NAME("RSSurfaceCaptureTaskParallel::CheckModifiers");
70     bool needSync = RSMainThread::Instance()->IsOcclusionNodesNeedSync(id, useCurWindow) ||
71         RSMainThread::Instance()->IsHardwareEnabledNodesNeedSync();
72     if (!needSync) {
73         return;
74     }
75     std::function<void()> syncTask = []() -> void {
76         RS_TRACE_NAME("RSSurfaceCaptureTaskParallel::SyncModifiers");
77         auto& pendingSyncNodes = RSMainThread::Instance()->GetContext().pendingSyncNodes_;
78         for (auto& [id, weakPtr] : pendingSyncNodes) {
79             auto node = weakPtr.lock();
80             if (node == nullptr) {
81                 continue;
82             }
83             if (!RSUifirstManager::Instance().CollectSkipSyncNode(node)) {
84                 node->Sync();
85             } else {
86                 node->SkipSync();
87             }
88         }
89         pendingSyncNodes.clear();
90         RSUifirstManager::Instance().UifirstCurStateClear();
91     };
92     RSUniRenderThread::Instance().PostSyncTask(syncTask);
93 }
94 
Capture(NodeId id,sptr<RSISurfaceCaptureCallback> callback,const RSSurfaceCaptureConfig & captureConfig,bool isSystemCalling,bool isFreeze)95 void RSSurfaceCaptureTaskParallel::Capture(NodeId id, sptr<RSISurfaceCaptureCallback> callback,
96     const RSSurfaceCaptureConfig& captureConfig, bool isSystemCalling, bool isFreeze)
97 {
98     if (callback == nullptr) {
99         RS_LOGE("RSSurfaceCaptureTaskParallel::Capture nodeId:[%{public}" PRIu64 "], callback is nullptr", id);
100         return;
101     }
102     std::shared_ptr<RSSurfaceCaptureTaskParallel> captureHandle =
103         std::make_shared<RSSurfaceCaptureTaskParallel>(id, captureConfig);
104     if (captureHandle == nullptr) {
105         RS_LOGD("RSSurfaceCaptureTaskParallel::Capture captureHandle is nullptr!");
106         callback->OnSurfaceCapture(id, nullptr);
107         return;
108     }
109     if (!captureHandle->CreateResources()) {
110         callback->OnSurfaceCapture(id, nullptr);
111         return;
112     }
113 
114     std::function<void()> captureTask = [captureHandle, id, callback, isSystemCalling, isFreeze]() -> void {
115         RS_TRACE_NAME("RSSurfaceCaptureTaskParallel::TakeSurfaceCapture");
116         if (!captureHandle->Run(callback, isSystemCalling, isFreeze)) {
117             callback->OnSurfaceCapture(id, nullptr);
118         }
119     };
120     RSUniRenderThread::Instance().PostSyncTask(captureTask);
121 }
122 
ClearCacheImageByFreeze(NodeId id)123 void RSSurfaceCaptureTaskParallel::ClearCacheImageByFreeze(NodeId id)
124 {
125     auto node = RSMainThread::Instance()->GetContext().GetNodeMap().GetRenderNode(id);
126     if (node == nullptr) {
127         RS_LOGE("RSSurfaceCaptureTaskParallel::CreateResources: Invalid nodeId:[%{public}" PRIu64 "]", id);
128         return;
129     }
130     if (auto surfaceNode = node->ReinterpretCastTo<RSSurfaceRenderNode>()) {
131         auto surfaceNodeDrawable = std::static_pointer_cast<DrawableV2::RSRenderNodeDrawable>(
132             DrawableV2::RSRenderNodeDrawableAdapter::OnGenerate(surfaceNode));
133         std::function<void()> clearCacheTask = [id, surfaceNodeDrawable]() -> void {
134             surfaceNodeDrawable->SetCacheImageByCapture(nullptr);
135         };
136         RSUniRenderThread::Instance().PostTask(clearCacheTask);
137     }
138 }
139 
CreateResources()140 bool RSSurfaceCaptureTaskParallel::CreateResources()
141 {
142     RS_LOGD("RSSurfaceCaptureTaskParallel capture nodeId:[%{public}" PRIu64 "] scaleX:%{public}f"
143         " scaleY:%{public}f useCurWindow:%{public}d", nodeId_, captureConfig_.scaleX,
144         captureConfig_.scaleY,  captureConfig_.useCurWindow);
145     if (ROSEN_EQ(captureConfig_.scaleX, 0.f) || ROSEN_EQ(captureConfig_.scaleY, 0.f) ||
146         captureConfig_.scaleX < 0.f || captureConfig_.scaleY < 0.f ||
147         captureConfig_.scaleX > 1.f || captureConfig_.scaleY > 1.f) {
148         RS_LOGE("RSSurfaceCaptureTaskParallel::CreateResources: SurfaceCapture scale is invalid.");
149         return false;
150     }
151     auto node = RSMainThread::Instance()->GetContext().GetNodeMap().GetRenderNode(nodeId_);
152     if (node == nullptr) {
153         RS_LOGE("RSSurfaceCaptureTaskParallel::CreateResources: Invalid nodeId:[%{public}" PRIu64 "]",
154             nodeId_);
155         return false;
156     }
157 
158     if (auto surfaceNode = node->ReinterpretCastTo<RSSurfaceRenderNode>()) {
159         auto curNode = surfaceNode;
160         if (!captureConfig_.useCurWindow) {
161             auto parentNode = RSBaseRenderNode::ReinterpretCast<RSSurfaceRenderNode>(surfaceNode->GetParent().lock());
162             if (parentNode && parentNode->IsLeashWindow() && parentNode->ShouldPaint()) {
163                 curNode = parentNode;
164             }
165         }
166         if (!curNode->ShouldPaint()) {
167             RS_LOGE("RSSurfaceCaptureTaskParallel::CreateResources: Node should not paint!");
168             return false;
169         }
170 
171         surfaceNodeDrawable_ = std::static_pointer_cast<DrawableV2::RSRenderNodeDrawable>(
172             DrawableV2::RSRenderNodeDrawableAdapter::OnGenerate(curNode));
173         pixelMap_ = CreatePixelMapBySurfaceNode(curNode);
174     } else if (auto displayNode = node->ReinterpretCastTo<RSDisplayRenderNode>()) {
175         displayNodeDrawable_ = std::static_pointer_cast<DrawableV2::RSRenderNodeDrawable>(
176             DrawableV2::RSRenderNodeDrawableAdapter::OnGenerate(displayNode));
177         pixelMap_ = CreatePixelMapByDisplayNode(displayNode);
178     } else {
179         RS_LOGE("RSSurfaceCaptureTaskParallel::CreateResources: Invalid RSRenderNodeType!");
180         return false;
181     }
182     if (pixelMap_ == nullptr) {
183         RS_LOGE("RSSurfaceCaptureTaskParallel::CreateResources: pixelMap_ is nullptr!");
184         return false;
185     }
186     return true;
187 }
188 
Run(sptr<RSISurfaceCaptureCallback> callback,bool isSystemCalling,bool isFreeze)189 bool RSSurfaceCaptureTaskParallel::Run(
190     sptr<RSISurfaceCaptureCallback> callback, bool isSystemCalling, bool isFreeze)
191 {
192 #if defined(RS_ENABLE_GL) || defined(RS_ENABLE_VK)
193     SetupGpuContext();
194     std::string nodeName("RSSurfaceCaptureTaskParallel");
195     RSTagTracker tagTracker(gpuContext_.get(), nodeId_, RSTagTracker::TAGTYPE::TAG_CAPTURE, nodeName);
196 #endif
197     auto surface = CreateSurface(pixelMap_);
198     if (surface == nullptr) {
199         RS_LOGE("RSSurfaceCaptureTaskParallel::Run: surface is nullptr!");
200         return false;
201     }
202 
203     RSPaintFilterCanvas canvas(surface.get());
204     canvas.Scale(captureConfig_.scaleX, captureConfig_.scaleY);
205     canvas.SetDisableFilterCache(true);
206     RSSurfaceRenderParams* curNodeParams = nullptr;
207     // Currently, capture do not support HDR display
208     canvas.SetCapture(true);
209     if (surfaceNodeDrawable_) {
210         curNodeParams = static_cast<RSSurfaceRenderParams*>(surfaceNodeDrawable_->GetRenderParams().get());
211         // make sure the previous uifirst task is completed.
212         if (!RSUiFirstProcessStateCheckerHelper::CheckMatchAndWaitNotify(*curNodeParams, false)) {
213             return false;
214         }
215         RSUiFirstProcessStateCheckerHelper stateCheckerHelper(
216             curNodeParams->GetFirstLevelNodeId(), curNodeParams->GetUifirstRootNodeId());
217         RSUniRenderThread::SetCaptureParam(
218             CaptureParam(true, true, false, captureConfig_.scaleX, captureConfig_.scaleY, true, isSystemCalling));
219         surfaceNodeDrawable_->OnCapture(canvas);
220         if (isFreeze) {
221             surfaceNodeDrawable_->SetCacheImageByCapture(surface->GetImageSnapshot());
222         }
223     } else if (displayNodeDrawable_) {
224         RSUniRenderThread::SetCaptureParam(
225             CaptureParam(true, false, false, captureConfig_.scaleX, captureConfig_.scaleY));
226         displayNodeDrawable_->OnCapture(canvas);
227     } else {
228         RS_LOGE("RSSurfaceCaptureTaskParallel::Run: Invalid RSRenderNodeDrawable!");
229         return false;
230     }
231     RSUniRenderThread::ResetCaptureParam();
232 
233 #if (defined (RS_ENABLE_GL) || defined (RS_ENABLE_VK)) && (defined RS_ENABLE_EGLIMAGE)
234 #ifdef RS_ENABLE_UNI_RENDER
235     RSUniRenderUtil::OptimizedFlushAndSubmit(surface, gpuContext_.get(), !RSSystemProperties::IsPcType());
236     if (curNodeParams && curNodeParams->IsNodeToBeCaptured()) {
237         RSUifirstManager::Instance().AddCapturedNodes(curNodeParams->GetId());
238     }
239     if (RSSystemProperties::GetSnapshotWithDMAEnabled()) {
240         auto copytask = CreateSurfaceSyncCopyTask(surface, std::move(pixelMap_),
241             nodeId_, callback, finalRotationAngle_, captureConfig_.useDma);
242         if (!copytask) {
243             RS_LOGE("RSSurfaceCaptureTaskParallel::Run: create capture task failed!");
244             return false;
245         }
246         RSBackgroundThread::Instance().PostTask(copytask);
247         return true;
248     } else {
249         std::shared_ptr<Drawing::Image> img(surface.get()->GetImageSnapshot());
250         if (!img) {
251             RS_LOGE("RSSurfaceCaptureTaskParallel::Run: img is nullptr");
252             return false;
253         }
254         if (!CopyDataToPixelMap(img, pixelMap_, colorSpace_)) {
255             RS_LOGE("RSSurfaceCaptureTaskParallel::Run: CopyDataToPixelMap failed");
256             return false;
257         }
258     }
259 #endif
260 #endif
261     if (finalRotationAngle_) {
262         pixelMap_->rotate(finalRotationAngle_);
263     }
264     // To get dump image
265     // execute "param set rosen.dumpsurfacetype.enabled 3 && setenforce 0"
266     RSBaseRenderUtil::WritePixelMapToPng(*pixelMap_);
267     callback->OnSurfaceCapture(nodeId_, pixelMap_.get());
268     return true;
269 }
270 
CreatePixelMapBySurfaceNode(std::shared_ptr<RSSurfaceRenderNode> node)271 std::unique_ptr<Media::PixelMap> RSSurfaceCaptureTaskParallel::CreatePixelMapBySurfaceNode(
272     std::shared_ptr<RSSurfaceRenderNode> node)
273 {
274     if (node == nullptr) {
275         RS_LOGE("RSSurfaceCaptureTaskParallel::CreatePixelMapBySurfaceNode: node == nullptr");
276         return nullptr;
277     }
278     int pixmapWidth = node->GetRenderProperties().GetBoundsWidth();
279     int pixmapHeight = node->GetRenderProperties().GetBoundsHeight();
280 
281     Media::InitializationOptions opts;
282     opts.size.width = ceil(pixmapWidth * captureConfig_.scaleX);
283     opts.size.height = ceil(pixmapHeight * captureConfig_.scaleY);
284     RS_LOGD("RSSurfaceCaptureTaskParallel::CreatePixelMapBySurfaceNode: NodeId:[%{public}" PRIu64 "],"
285         " origin pixelmap size: [%{public}u, %{public}u],"
286         " created pixelmap size: [%{public}u, %{public}u],"
287         " scale: [%{public}f, %{public}f],"
288         " useDma: [%{public}d], useCurWindow: [%{public}d]",
289         node->GetId(), pixmapWidth, pixmapHeight, opts.size.width, opts.size.height,
290         captureConfig_.scaleX, captureConfig_.scaleY, captureConfig_.useDma, captureConfig_.useCurWindow);
291     return Media::PixelMap::Create(opts);
292 }
293 
CreatePixelMapByDisplayNode(std::shared_ptr<RSDisplayRenderNode> node)294 std::unique_ptr<Media::PixelMap> RSSurfaceCaptureTaskParallel::CreatePixelMapByDisplayNode(
295     std::shared_ptr<RSDisplayRenderNode> node)
296 {
297     if (node == nullptr) {
298         RS_LOGE("RSSurfaceCaptureTaskParallel::CreatePixelMapByDisplayNode: node is nullptr");
299         return nullptr;
300     }
301     uint64_t screenId = node->GetScreenId();
302     sptr<RSScreenManager> screenManager = CreateOrGetScreenManager();
303     if (!screenManager) {
304         RS_LOGE("RSSurfaceCaptureTaskParallel::CreatePixelMapByDisplayNode: screenManager is nullptr!");
305         return nullptr;
306     }
307     auto screenInfo = screenManager->QueryScreenInfo(screenId);
308     screenCorrection_ = screenManager->GetScreenCorrection(screenId);
309     screenRotation_ = node->GetScreenRotation();
310     finalRotationAngle_ = CalPixelMapRotation();
311     uint32_t pixmapWidth = screenInfo.width;
312     uint32_t pixmapHeight = screenInfo.height;
313 
314     Media::InitializationOptions opts;
315     opts.size.width = ceil(pixmapWidth * captureConfig_.scaleX);
316     opts.size.height = ceil(pixmapHeight * captureConfig_.scaleY);
317     RS_LOGI("RSSurfaceCaptureTaskParallel::CreatePixelMapByDisplayNode: NodeId:[%{public}" PRIu64 "],"
318         " origin pixelmap size: [%{public}u, %{public}u],"
319         " scale: [%{public}f, %{public}f],"
320         " useDma: [%{public}d], screenRotation_: [%{public}d], screenCorrection_: [%{public}d]",
321         node->GetId(), pixmapWidth, pixmapHeight, captureConfig_.scaleX, captureConfig_.scaleY,
322         captureConfig_.useDma, screenRotation_, screenCorrection_);
323     return Media::PixelMap::Create(opts);
324 }
325 
CreateSurface(const std::unique_ptr<Media::PixelMap> & pixelmap)326 std::shared_ptr<Drawing::Surface> RSSurfaceCaptureTaskParallel::CreateSurface(
327     const std::unique_ptr<Media::PixelMap>& pixelmap)
328 {
329     if (pixelmap == nullptr) {
330         RS_LOGE("RSSurfaceCaptureTaskParallel::CreateSurface: pixelmap == nullptr");
331         return nullptr;
332     }
333     auto address = const_cast<uint32_t*>(pixelmap->GetPixel32(0, 0));
334     if (address == nullptr) {
335         RS_LOGE("RSSurfaceCaptureTaskParallel::CreateSurface: address == nullptr");
336         return nullptr;
337     }
338     GraphicColorGamut colorGamut = GraphicColorGamut::GRAPHIC_COLOR_GAMUT_SRGB;
339     RSDisplayRenderParams* curNodeParams = nullptr;
340     if (displayNodeDrawable_) {
341         curNodeParams = static_cast<RSDisplayRenderParams*>(displayNodeDrawable_->GetRenderParams().get());
342         colorGamut = curNodeParams->GetNewColorSpace();
343     }
344     colorSpace_ = RSBaseRenderEngine::ConvertColorGamutToDrawingColorSpace(colorGamut);
345     Drawing::ImageInfo info = Drawing::ImageInfo{pixelmap->GetWidth(), pixelmap->GetHeight(),
346         Drawing::ColorType::COLORTYPE_RGBA_8888, Drawing::AlphaType::ALPHATYPE_PREMUL, colorSpace_};
347 
348 #if (defined RS_ENABLE_GL) && (defined RS_ENABLE_EGLIMAGE)
349     if (RSSystemProperties::GetGpuApiType() == GpuApiType::OPENGL) {
350         auto renderEngine = RSUniRenderThread::Instance().GetRenderEngine();
351         if (renderEngine == nullptr) {
352             RS_LOGE("RSSurfaceCaptureTaskParallel::CreateSurface: renderEngine is nullptr");
353             return nullptr;
354         }
355         auto renderContext = renderEngine->GetRenderContext();
356         if (renderContext == nullptr) {
357             RS_LOGE("RSSurfaceCaptureTaskParallel::CreateSurface: renderContext is nullptr");
358             return nullptr;
359         }
360         renderContext->SetUpGpuContext(nullptr);
361         return Drawing::Surface::MakeRenderTarget(renderContext->GetDrGPUContext(), false, info);
362     }
363 #endif
364 #ifdef RS_ENABLE_VK
365     if (RSSystemProperties::GetGpuApiType() == GpuApiType::VULKAN ||
366         RSSystemProperties::GetGpuApiType() == GpuApiType::DDGR) {
367         return Drawing::Surface::MakeRenderTarget(gpuContext_.get(), false, info);
368     }
369 #endif
370 
371     return Drawing::Surface::MakeRasterDirect(info, address, pixelmap->GetRowBytes());
372 }
373 
SetupGpuContext()374 void RSSurfaceCaptureTaskParallel::SetupGpuContext()
375 {
376     auto renderEngine = RSUniRenderThread::Instance().GetRenderEngine();
377     if (renderEngine == nullptr) {
378         RS_LOGE("RSSurfaceCaptureTaskParallel::SetupGpuContext: renderEngine is nullptr");
379         return;
380     }
381     auto renderContext = renderEngine->GetRenderContext();
382     gpuContext_ = renderContext != nullptr ? renderContext->GetSharedDrGPUContext() : nullptr;
383     if (gpuContext_ == nullptr) {
384         RS_LOGW("RSSurfaceCaptureTaskParallel::SetupGpuContext gpuContext_ is nullptr");
385     }
386 }
387 
CalPixelMapRotation()388 int32_t RSSurfaceCaptureTaskParallel::CalPixelMapRotation()
389 {
390     auto screenRotation = ScreenRotationMapping(screenRotation_);
391     auto screenCorrection = ScreenRotationMapping(screenCorrection_);
392     int32_t rotation = screenRotation - screenCorrection;
393     return rotation;
394 }
395 
396 #ifdef RS_ENABLE_UNI_RENDER
CreateSurfaceSyncCopyTask(std::shared_ptr<Drawing::Surface> surface,std::unique_ptr<Media::PixelMap> pixelMap,NodeId id,sptr<RSISurfaceCaptureCallback> callback,int32_t rotation,bool useDma)397 std::function<void()> RSSurfaceCaptureTaskParallel::CreateSurfaceSyncCopyTask(
398     std::shared_ptr<Drawing::Surface> surface, std::unique_ptr<Media::PixelMap> pixelMap,
399     NodeId id, sptr<RSISurfaceCaptureCallback> callback, int32_t rotation, bool useDma)
400 {
401     if (surface == nullptr) {
402         RS_LOGE("RSSurfaceCaptureTaskParallel: nodeId:[%{public}" PRIu64 "], surface is nullptr", id);
403         return {};
404     }
405     Drawing::BackendTexture backendTexture = surface->GetBackendTexture();
406     if (!backendTexture.IsValid()) {
407         RS_LOGE("RSSurfaceCaptureTaskParallel: SkiaSurface bind Image failed: BackendTexture is invalid");
408         return {};
409     }
410     auto wrapper = std::make_shared<std::tuple<std::unique_ptr<Media::PixelMap>>>();
411     std::get<0>(*wrapper) = std::move(pixelMap);
412     auto wrapperSf = std::make_shared<std::tuple<std::shared_ptr<Drawing::Surface>>>();
413     std::get<0>(*wrapperSf) = std::move(surface);
414     std::function<void()> copytask = [wrapper, callback, backendTexture, wrapperSf, id, rotation, useDma]() -> void {
415         RS_TRACE_NAME_FMT("copy and send capture useDma:%d", useDma);
416         if (callback == nullptr) {
417             RS_LOGE("RSSurfaceCaptureTaskParallel: nodeId:[%{public}" PRIu64 "], callback is nullptr", id);
418             return;
419         }
420         auto colorSpace = std::get<0>(*wrapperSf)->GetImageInfo().GetColorSpace();
421         if (!backendTexture.IsValid()) {
422             RS_LOGE("RSSurfaceCaptureTaskParallel: Surface bind Image failed: BackendTexture is invalid");
423             callback->OnSurfaceCapture(id, nullptr);
424             RSUniRenderUtil::ClearNodeCacheSurface(
425                 std::move(std::get<0>(*wrapperSf)), nullptr, UNI_MAIN_THREAD_INDEX, 0);
426             return;
427         }
428         auto pixelmap = std::move(std::get<0>(*wrapper));
429         if (pixelmap == nullptr) {
430             RS_LOGE("RSSurfaceCaptureTaskParallel: pixelmap == nullptr");
431             callback->OnSurfaceCapture(id, nullptr);
432             RSUniRenderUtil::ClearNodeCacheSurface(
433                 std::move(std::get<0>(*wrapperSf)), nullptr, UNI_MAIN_THREAD_INDEX, 0);
434             return;
435         }
436 
437         Drawing::ImageInfo info = Drawing::ImageInfo{ pixelmap->GetWidth(), pixelmap->GetHeight(),
438             Drawing::COLORTYPE_RGBA_8888, Drawing::ALPHATYPE_PREMUL, colorSpace};
439         Drawing::TextureOrigin textureOrigin = Drawing::TextureOrigin::BOTTOM_LEFT;
440         Drawing::BitmapFormat bitmapFormat =
441             Drawing::BitmapFormat{ Drawing::COLORTYPE_RGBA_8888, Drawing::ALPHATYPE_PREMUL };
442         std::shared_ptr<Drawing::Surface> surface;
443         auto grContext = RSBackgroundThread::Instance().GetShareGPUContext();
444 #if defined(ROSEN_OHOS) && defined(RS_ENABLE_VK)
445         DmaMem dmaMem;
446         if (useDma && RSMainThread::Instance()->GetDeviceType() == DeviceType::PHONE &&
447             (RSSystemProperties::GetGpuApiType() == GpuApiType::VULKAN ||
448             RSSystemProperties::GetGpuApiType() == GpuApiType::DDGR)) {
449             sptr<SurfaceBuffer> surfaceBuffer = dmaMem.DmaMemAlloc(info, pixelmap);
450             if (surfaceBuffer != nullptr && colorSpace != nullptr && !colorSpace->IsSRGB()) {
451                 surfaceBuffer->SetSurfaceBufferColorGamut(GraphicColorGamut::GRAPHIC_COLOR_GAMUT_DISPLAY_P3);
452             }
453             surface = dmaMem.GetSurfaceFromSurfaceBuffer(surfaceBuffer, grContext);
454             if (surface == nullptr) {
455                 RS_LOGE("RSSurfaceCaptureTaskParallel: GetSurfaceFromSurfaceBuffer fail.");
456                 callback->OnSurfaceCapture(id, nullptr);
457                 RSUniRenderUtil::ClearNodeCacheSurface(
458                     std::move(std::get<0>(*wrapperSf)), nullptr, UNI_MAIN_THREAD_INDEX, 0);
459                 return;
460             }
461             auto tmpImg = std::make_shared<Drawing::Image>();
462             DrawCapturedImg(*tmpImg, *surface, backendTexture, textureOrigin, bitmapFormat);
463         } else {
464 #else
465         {
466 #endif
467             auto tmpImg = std::make_shared<Drawing::Image>();
468             tmpImg->BuildFromTexture(*grContext, backendTexture.GetTextureInfo(),
469                 textureOrigin, bitmapFormat, colorSpace);
470             if (!CopyDataToPixelMap(tmpImg, pixelmap, colorSpace)) {
471                 RS_LOGE("RSSurfaceCaptureTaskParallel: CopyDataToPixelMap failed");
472                 callback->OnSurfaceCapture(id, nullptr);
473                 RSUniRenderUtil::ClearNodeCacheSurface(
474                     std::move(std::get<0>(*wrapperSf)), nullptr, UNI_MAIN_THREAD_INDEX, 0);
475                 return;
476             }
477         }
478         if (rotation) {
479             pixelmap->rotate(rotation);
480         }
481         // To get dump image
482         // execute "param set rosen.dumpsurfacetype.enabled 3 && setenforce 0"
483         RSBaseRenderUtil::WritePixelMapToPng(*pixelmap);
484         callback->OnSurfaceCapture(id, pixelmap.get());
485         RSBackgroundThread::Instance().CleanGrResource();
486         RSUniRenderUtil::ClearNodeCacheSurface(
487             std::move(std::get<0>(*wrapperSf)), nullptr, UNI_MAIN_THREAD_INDEX, 0);
488     };
489     return copytask;
490 }
491 #endif
492 
493 #if defined(ROSEN_OHOS) && defined(RS_ENABLE_VK)
494 DmaMem::~DmaMem()
495 {
496     ReleaseDmaMemory();
497 }
498 
499 void DmaMem::ReleaseDmaMemory()
500 {
501     if (nativeWindowBuffer_ != nullptr) {
502         DestroyNativeWindowBuffer(nativeWindowBuffer_);
503         nativeWindowBuffer_ = nullptr;
504     }
505 }
506 
507 sptr<SurfaceBuffer> DmaMem::DmaMemAlloc(Drawing::ImageInfo &dstInfo, const std::unique_ptr<Media::PixelMap>& pixelmap)
508 {
509 #if defined(_WIN32) || defined(_APPLE) || defined(A_PLATFORM) || defined(IOS_PLATFORM)
510     RS_LOGE("Unsupport dma mem alloc");
511     return nullptr;
512 #else
513     if (pixelmap == nullptr) {
514         RS_LOGE("DmaMem::DmaMemAlloc: pixelmap is nullptr");
515         return nullptr;
516     }
517     sptr<SurfaceBuffer> surfaceBuffer = SurfaceBuffer::Create();
518     if (!surfaceBuffer) {
519         RS_LOGE("DmaMem::DmaMemAlloc: surfaceBuffer create failed");
520         return nullptr;
521     }
522     BufferRequestConfig requestConfig = {
523         .width = dstInfo.GetWidth(),
524         .height = dstInfo.GetHeight(),
525         .strideAlignment = 0x8, // set 0x8 as default value to alloc SurfaceBufferImpl
526         .format = GRAPHIC_PIXEL_FMT_RGBA_8888, // PixelFormat
527         .usage = BUFFER_USAGE_CPU_READ | BUFFER_USAGE_HW_RENDER | BUFFER_USAGE_HW_TEXTURE | BUFFER_USAGE_MEM_DMA,
528         .timeout = 0,
529         .colorGamut = GraphicColorGamut::GRAPHIC_COLOR_GAMUT_SRGB,
530         .transform = GraphicTransformType::GRAPHIC_ROTATE_NONE,
531     };
532     GSError ret = surfaceBuffer->Alloc(requestConfig);
533     if (ret != GSERROR_OK) {
534         RS_LOGE("DmaMem::DmaMemAlloc: surfaceBuffer alloc failed, %{public}s", GSErrorStr(ret).c_str());
535         return nullptr;
536     }
537     void* nativeBuffer = surfaceBuffer.GetRefPtr();
538     OHOS::RefBase *ref = reinterpret_cast<OHOS::RefBase *>(nativeBuffer);
539     ref->IncStrongRef(ref);
540     int32_t bufferSize = pixelmap->GetByteCount();
541     pixelmap->SetPixelsAddr(surfaceBuffer->GetVirAddr(), nativeBuffer, bufferSize,
542         Media::AllocatorType::DMA_ALLOC, nullptr);
543     return surfaceBuffer;
544 #endif
545 }
546 
547 static inline void DeleteVkImage(void *context)
548 {
549     NativeBufferUtils::VulkanCleanupHelper *cleanupHelper =
550         static_cast<NativeBufferUtils::VulkanCleanupHelper *> (context);
551     if (cleanupHelper != nullptr) {
552         cleanupHelper->UnRef();
553     }
554 }
555 
556 std::shared_ptr<Drawing::Surface> DmaMem::GetSurfaceFromSurfaceBuffer(
557     sptr<SurfaceBuffer> surfaceBuffer, std::shared_ptr<Drawing::GPUContext> gpuContext)
558 {
559     if (surfaceBuffer == nullptr || gpuContext == nullptr) {
560         RS_LOGE("GetSurfaceFromSurfaceBuffer surfaceBuffer or gpuContext is nullptr");
561         return nullptr;
562     }
563     if (nativeWindowBuffer_ == nullptr) {
564         nativeWindowBuffer_ = CreateNativeWindowBufferFromSurfaceBuffer(&surfaceBuffer);
565         if (!nativeWindowBuffer_) {
566             RS_LOGE("DmaMem::GetSurfaceFromSurfaceBuffer: nativeWindowBuffer_ is nullptr");
567             return nullptr;
568         }
569     }
570 
571     Drawing::BackendTexture backendTextureTmp =
572         NativeBufferUtils::MakeBackendTextureFromNativeBuffer(nativeWindowBuffer_,
573             surfaceBuffer->GetWidth(), surfaceBuffer->GetHeight());
574     if (!backendTextureTmp.IsValid()) {
575         return nullptr;
576     }
577 
578     auto vkTextureInfo = backendTextureTmp.GetTextureInfo().GetVKTextureInfo();
579     if (vkTextureInfo == nullptr) {
580         return nullptr;
581     }
582     vkTextureInfo->imageUsageFlags = vkTextureInfo->imageUsageFlags | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
583     auto cleanUpHelper = new NativeBufferUtils::VulkanCleanupHelper(RsVulkanContext::GetSingleton(),
584         vkTextureInfo->vkImage, vkTextureInfo->vkAlloc.memory);
585     if (cleanUpHelper == nullptr) {
586         return nullptr;
587     }
588     // attention: cleanUpHelper will be delete by NativeBufferUtils::DeleteVkImage, don't delete again
589     auto colorSpace =
590         RSBaseRenderEngine::ConvertColorGamutToDrawingColorSpace(surfaceBuffer->GetSurfaceBufferColorGamut());
591     auto drawingSurface = Drawing::Surface::MakeFromBackendTexture(
592         gpuContext.get(),
593         backendTextureTmp.GetTextureInfo(),
594         Drawing::TextureOrigin::TOP_LEFT,
595         1, Drawing::ColorType::COLORTYPE_RGBA_8888, colorSpace,
596         NativeBufferUtils::DeleteVkImage, cleanUpHelper);
597     return drawingSurface;
598 }
599 #endif
600 } // namespace Rosen
601 } // namespace OHOS
602