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