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