• 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 "feature/capture/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 "feature/hdr/rs_hdr_util.h"
28 #include "feature/uifirst/rs_uifirst_manager.h"
29 #include "feature_cfg/graphic_feature_param_manager.h"
30 #include "memory/rs_tag_tracker.h"
31 #include "params/rs_surface_render_params.h"
32 #include "pipeline/render_thread/rs_base_render_engine.h"
33 #include "pipeline/render_thread/rs_uni_render_util.h"
34 #include "pipeline/rs_base_render_node.h"
35 #include "pipeline/rs_screen_render_node.h"
36 #include "pipeline/main_thread/rs_main_thread.h"
37 #include "pipeline/rs_paint_filter_canvas.h"
38 #include "pipeline/rs_pointer_window_manager.h"
39 #include "pipeline/main_thread/rs_render_service_connection.h"
40 #include "pipeline/rs_surface_render_node.h"
41 #include "pipeline/rs_uni_render_judgement.h"
42 #include "platform/drawing/rs_surface.h"
43 #include "render/rs_drawing_filter.h"
44 #include "render/rs_skia_filter.h"
45 #include "screen_manager/rs_screen_manager.h"
46 #include "screen_manager/rs_screen_mode_info.h"
47 #include "pipeline/rs_logical_display_render_node.h"
48 
49 namespace OHOS {
50 namespace Rosen {
51 namespace {
52 #ifdef RS_ENABLE_GPU
DrawCapturedImg(Drawing::Image & image,Drawing::Surface & surface,const Drawing::BackendTexture & backendTexture,Drawing::TextureOrigin & textureOrigin,Drawing::BitmapFormat & bitmapFormat)53 inline void DrawCapturedImg(Drawing::Image& image,
54     Drawing::Surface& surface, const Drawing::BackendTexture& backendTexture,
55     Drawing::TextureOrigin& textureOrigin, Drawing::BitmapFormat& bitmapFormat)
56 {
57     RSPaintFilterCanvas canvas(&surface);
58     auto gpuContext = canvas.GetGPUContext();
59     if (gpuContext == nullptr) {
60         RS_LOGE("DrawCapturedImg failed: gpuContext is nullptr");
61         return;
62     }
63     auto colorSpace = surface.GetImageInfo().GetColorSpace();
64     image.BuildFromTexture(*gpuContext, backendTexture.GetTextureInfo(),
65         textureOrigin, bitmapFormat, colorSpace);
66     canvas.DrawImage(image, 0.f, 0.f, Drawing::SamplingOptions());
67     surface.FlushAndSubmit(true);
68 }
69 #endif
70 
PixelMapSamplingDump(std::unique_ptr<Media::PixelMap> & pixelmap,int32_t x,int32_t y)71 uint32_t PixelMapSamplingDump(std::unique_ptr<Media::PixelMap>& pixelmap, int32_t x, int32_t y)
72 {
73     if (pixelmap == nullptr) {
74         RS_LOGE("PixelMapSamplingDump fail, pixelmap is nullptr");
75         return 0;
76     }
77     if (x < 0 || x >= pixelmap->GetWidth() || y < 0 || y >= pixelmap->GetHeight()) {
78         RS_LOGE("PixelMapSamplingDump fail, x or y is invalid");
79         return 0;
80     }
81     uint32_t pixel = 0;
82     pixelmap->ReadPixel({x, y}, pixel);
83     return pixel;
84 }
85 }
86 
CheckModifiers(NodeId id,bool useCurWindow)87 void RSSurfaceCaptureTaskParallel::CheckModifiers(NodeId id, bool useCurWindow)
88 {
89     RS_TRACE_NAME("RSSurfaceCaptureTaskParallel::CheckModifiers");
90     bool needSync = RSMainThread::Instance()->IsOcclusionNodesNeedSync(id, useCurWindow) ||
91         RSPointerWindowManager::Instance().GetBoundHasUpdate() ||
92         RSMainThread::Instance()->IsHardwareEnabledNodesNeedSync();
93     if (!needSync) {
94         return;
95     }
96     std::function<void()> syncTask = []() -> void {
97         RS_TRACE_NAME("RSSurfaceCaptureTaskParallel::SyncModifiers");
98         RS_LOGI("RSSurfaceCaptureTaskParallel::SyncModifiers");
99         RSPointerWindowManager::Instance().UpdatePointerInfo();
100         auto& pendingSyncNodes = RSMainThread::Instance()->GetContext().pendingSyncNodes_;
101         int skipTimes = 0;
102         for (auto& [id, weakPtr] : pendingSyncNodes) {
103             auto node = weakPtr.lock();
104             if (node == nullptr) {
105                 continue;
106             }
107             if (!RSUifirstManager::Instance().CollectSkipSyncNode(node)) {
108                 node->Sync();
109             } else {
110                 node->SkipSync();
111                 skipTimes++;
112             }
113         }
114         if (skipTimes != 0) {
115             RS_LOGW("RSSurfaceCaptureTaskParallel::CheckModifiers SkipSync times: [%{public}d]", skipTimes);
116         }
117         pendingSyncNodes.clear();
118         RSUifirstManager::Instance().UifirstCurStateClear();
119     };
120     RSUniRenderThread::Instance().PostSyncTask(syncTask);
121 }
122 
Capture(sptr<RSISurfaceCaptureCallback> callback,const RSSurfaceCaptureParam & captureParam)123 void RSSurfaceCaptureTaskParallel::Capture(
124     sptr<RSISurfaceCaptureCallback> callback, const RSSurfaceCaptureParam& captureParam)
125 {
126     if (callback == nullptr) {
127         RS_LOGE(
128             "RSSurfaceCaptureTaskParallel::Capture nodeId:[%{public}" PRIu64 "], callback is nullptr", captureParam.id);
129         return;
130     }
131 
132     std::shared_ptr<RSSurfaceCaptureTaskParallel> captureHandle =
133         std::make_shared<RSSurfaceCaptureTaskParallel>(captureParam.id, captureParam.config);
134     if (!captureHandle->CreateResources()) {
135         callback->OnSurfaceCapture(captureParam.id, captureParam.config, nullptr);
136         return;
137     }
138 
139     // When the HDR PixelMap is created, it indicates that an HDR screenshot is required.
140     if (captureHandle->UseScreenShotWithHDR()) {
141         std::function<void()> captureTask = [captureHandle, callback, captureParam]() -> void {
142             RS_TRACE_NAME("RSSurfaceCaptureTaskParallel::TakeSurfaceCaptureHDR");
143             if (!captureHandle->RunHDR(callback, captureParam)) {
144                 callback->OnSurfaceCapture(captureParam.id, captureParam.config, nullptr, nullptr);
145             }
146         };
147         RSUniRenderThread::Instance().PostSyncTask(captureTask);
148         return;
149     }
150 
151     std::function<void()> captureTask = [captureHandle, callback, captureParam]() -> void {
152         RS_TRACE_NAME("RSSurfaceCaptureTaskParallel::TakeSurfaceCapture");
153         if (!captureHandle->Run(callback, captureParam)) {
154             callback->OnSurfaceCapture(captureParam.id, captureParam.config, nullptr);
155         }
156     };
157     RSUniRenderThread::Instance().PostSyncTask(captureTask);
158 }
159 
ClearCacheImageByFreeze(NodeId id)160 void RSSurfaceCaptureTaskParallel::ClearCacheImageByFreeze(NodeId id)
161 {
162     auto node = RSMainThread::Instance()->GetContext().GetNodeMap().GetRenderNode(id);
163     if (node == nullptr) {
164         RS_LOGE("RSSurfaceCaptureTaskParallel::CreateResources: Invalid nodeId:[%{public}" PRIu64 "]", id);
165         return;
166     }
167     if (auto surfaceNode = node->ReinterpretCastTo<RSSurfaceRenderNode>()) {
168         auto surfaceNodeDrawable = std::static_pointer_cast<DrawableV2::RSRenderNodeDrawable>(
169             DrawableV2::RSRenderNodeDrawableAdapter::OnGenerate(surfaceNode));
170         std::function<void()> clearCacheTask = [id, surfaceNodeDrawable]() -> void {
171             surfaceNodeDrawable->SetCacheImageByCapture(nullptr);
172         };
173         RSUniRenderThread::Instance().PostTask(clearCacheTask);
174     }
175 }
176 
177 
CreateResources()178 bool RSSurfaceCaptureTaskParallel::CreateResources()
179 {
180     RS_LOGD("RSSurfaceCaptureTaskParallel capture nodeId:[%{public}" PRIu64 "] scaleX:%{public}f"
181         " scaleY:%{public}f useCurWindow:%{public}d", nodeId_, captureConfig_.scaleX,
182         captureConfig_.scaleY,  captureConfig_.useCurWindow);
183     if (ROSEN_EQ(captureConfig_.scaleX, 0.f) || ROSEN_EQ(captureConfig_.scaleY, 0.f) ||
184         captureConfig_.scaleX < 0.f || captureConfig_.scaleY < 0.f ||
185         captureConfig_.scaleX > 1.f || captureConfig_.scaleY > 1.f) {
186         RS_LOGE("RSSurfaceCaptureTaskParallel::CreateResources: SurfaceCapture scale is invalid.");
187         return false;
188     }
189     auto node = RSMainThread::Instance()->GetContext().GetNodeMap().GetRenderNode(nodeId_);
190     if (node == nullptr) {
191         RS_LOGE("RSSurfaceCaptureTaskParallel::CreateResources: Invalid nodeId:[%{public}" PRIu64 "]",
192             nodeId_);
193         return false;
194     }
195 
196     if (auto surfaceNode = node->ReinterpretCastTo<RSSurfaceRenderNode>()) {
197         surfaceNode_ = surfaceNode;
198         auto curNode = surfaceNode;
199         if (!captureConfig_.useCurWindow) {
200             auto parentNode = RSBaseRenderNode::ReinterpretCast<RSSurfaceRenderNode>(surfaceNode->GetParent().lock());
201             if (parentNode && parentNode->IsLeashWindow() && parentNode->ShouldPaint()) {
202                 curNode = parentNode;
203             }
204         }
205         if (!curNode->ShouldPaint()) {
206             RS_LOGW("RSSurfaceCaptureTaskParallel::CreateResources: curNode should not paint!");
207             return false;
208         }
209         if (curNode->GetSortedChildren()->size() == 0) {
210             RS_LOGW("RSSurfaceCaptureTaskParallel::CreateResources: curNode has no childrenList!");
211         }
212         surfaceNodeDrawable_ = std::static_pointer_cast<DrawableV2::RSRenderNodeDrawable>(
213             DrawableV2::RSRenderNodeDrawableAdapter::OnGenerate(curNode));
214         // When the window freeze capture invokes the F16 screenshot mode and window need use F16 capture,
215         // or when the HDR mode is invoked and the window contains HDR resources, an F16 buffer needs to be allocated.
216         bool isF16Capture = (captureConfig_.needF16WindowCaptureForScRGB && RSHdrUtil::NeedUseF16Capture(curNode)) ||
217             (captureConfig_.isHdrCapture && surfaceNode->GetHDRPresent());
218         pixelMap_ = CreatePixelMapBySurfaceNode(curNode, isF16Capture);
219         auto screenNode = std::static_pointer_cast<RSScreenRenderNode>(surfaceNode->GetAncestorScreenNode().lock());
220         if (screenNode) {
221             screenId_ = screenNode->GetScreenId();
222         }
223     } else if (auto displayNode = node->ReinterpretCastTo<RSLogicalDisplayRenderNode>()) {
224         displayNodeDrawable_ = std::static_pointer_cast<DrawableV2::RSRenderNodeDrawable>(
225             DrawableV2::RSRenderNodeDrawableAdapter::OnGenerate(displayNode));
226         pixelMap_ = CreatePixelMapByDisplayNode(displayNode);
227         auto screenNode = std::static_pointer_cast<RSScreenRenderNode>(displayNode->GetParent().lock());
228         // When the app calls HDR screenshot and the screen contains HDR content, two pixelmaps need to be captured.
229         if (captureConfig_.isHdrCapture && screenNode && (screenNode->GetDisplayHdrStatus() != HdrStatus::NO_HDR)) {
230             pixelMapHDR_ = CreatePixelMapByDisplayNode(displayNode, true);
231             SetUseScreenShotWithHDR(displayNodeDrawable_ && pixelMapHDR_);
232         }
233     } else {
234         RS_LOGE("RSSurfaceCaptureTaskParallel::CreateResources: Invalid RSRenderNodeType!");
235         return false;
236     }
237     if (pixelMap_ == nullptr) {
238         RS_LOGE("RSSurfaceCaptureTaskParallel::CreateResources: pixelMap_ is nullptr!");
239         return false;
240     }
241     return true;
242 }
243 
Run(sptr<RSISurfaceCaptureCallback> callback,const RSSurfaceCaptureParam & captureParam)244 bool RSSurfaceCaptureTaskParallel::Run(
245     sptr<RSISurfaceCaptureCallback> callback, const RSSurfaceCaptureParam& captureParam)
246 {
247 #if defined(RS_ENABLE_GL) || defined(RS_ENABLE_VK)
248     SetupGpuContext();
249     std::string nodeName("RSSurfaceCaptureTaskParallel");
250     RSTagTracker tagTracker(gpuContext_, nodeId_, RSTagTracker::TAGTYPE::TAG_CAPTURE, nodeName);
251 #endif
252     auto surface = CreateSurface(pixelMap_);
253     if (surface == nullptr) {
254         RS_LOGE("RSSurfaceCaptureTaskParallel::Run: surface is nullptr!");
255         return false;
256     }
257 
258     RSPaintFilterCanvas canvas(surface.get());
259     canvas.Scale(captureConfig_.scaleX, captureConfig_.scaleY);
260     const Drawing::Rect& rect = captureConfig_.mainScreenRect;
261     if (rect.GetWidth() > 0 && rect.GetHeight() > 0) {
262         canvas.ClipRect({0, 0, rect.GetWidth(), rect.GetHeight()});
263         canvas.Translate(-rect.GetLeft(), -rect.GetTop());
264     } else {
265         canvas.Translate(-boundsX_, -boundsY_);
266     }
267     canvas.SetDisableFilterCache(true);
268     RSSurfaceRenderParams* curNodeParams = nullptr;
269     if (surfaceNodeDrawable_) {
270         curNodeParams = static_cast<RSSurfaceRenderParams*>(surfaceNodeDrawable_->GetRenderParams().get());
271         RSUiFirstProcessStateCheckerHelper stateCheckerHelper(
272             curNodeParams->GetFirstLevelNodeId(), curNodeParams->GetUifirstRootNodeId());
273         RSUniRenderThread::SetCaptureParam(CaptureParam(true, true, false, true, captureParam.isSystemCalling,
274             captureParam.isSelfCapture, captureParam.blurParam.isNeedBlur));
275         DrawableV2::RSRenderNodeDrawable::ClearSnapshotProcessedNodeCount();
276         bool isHDRCapture = captureConfig_.isHdrCapture && curNodeParams->GetHDRPresent();
277         RSPaintFilterCanvas::ScreenshotType type = isHDRCapture ? RSPaintFilterCanvas::ScreenshotType::HDR_WINDOWSHOT :
278             RSPaintFilterCanvas::ScreenshotType::SDR_WINDOWSHOT;
279         canvas.SetScreenshotType(type);
280         canvas.SetHdrOn(isHDRCapture);
281         canvas.SetScreenId(screenId_);
282         canvas.SetIsWindowFreezeCapture(captureParam.isFreeze);
283         canvas.Clear(captureParam.config.backGroundColor);
284         surfaceNodeDrawable_->OnCapture(canvas);
285         RS_LOGI("RSSurfaceCaptureTaskParallel::Run: the number of total processedNodes: %{public}d",
286             DrawableV2::RSRenderNodeDrawable::GetSnapshotProcessedNodeCount());
287         DrawableV2::RSRenderNodeDrawable::ClearSnapshotProcessedNodeCount();
288         if (captureParam.isFreeze) {
289             surfaceNodeDrawable_->SetCacheImageByCapture(surface->GetImageSnapshot());
290         }
291         if (captureParam.blurParam.isNeedBlur) {
292             AddBlur(canvas, surface, captureParam.blurParam.blurRadius);
293         }
294     } else if (displayNodeDrawable_) {
295         auto type = RSPaintFilterCanvas::ScreenshotType::SDR_SCREENSHOT;
296         CaptureDisplayNode(*displayNodeDrawable_, canvas, captureParam, type);
297     } else {
298         RS_LOGE("RSSurfaceCaptureTaskParallel::Run: Invalid RSRenderNodeDrawable!");
299         return false;
300     }
301     RSUniRenderThread::ResetCaptureParam();
302 
303 #if (defined(RS_ENABLE_GL) || defined(RS_ENABLE_VK)) && \
304     (defined(RS_ENABLE_EGLIMAGE) && defined(RS_ENABLE_UNI_RENDER))
305     RSUniRenderUtil::OptimizedFlushAndSubmit(surface, gpuContext_.get(), GetFeatureParamValue("CaptureConfig",
306         &CaptureBaseParam::IsSnapshotWithDMAEnabled).value_or(false));
307     if (curNodeParams && curNodeParams->IsNodeToBeCaptured()) {
308         RSUifirstManager::Instance().AddCapturedNodes(curNodeParams->GetId());
309     }
310     bool snapshotDmaEnabled = system::GetBoolParameter("rosen.snapshotDma.enabled", true);
311     bool isEnableFeature = GetFeatureParamValue("CaptureConfig",
312         &CaptureBaseParam::IsSnapshotWithDMAEnabled).value_or(false);
313     if (snapshotDmaEnabled && isEnableFeature) {
314         auto copytask = CreateSurfaceSyncCopyTask(surface, std::move(pixelMap_),
315             nodeId_, captureConfig_, callback, finalRotationAngle_);
316         if (!copytask) {
317             RS_LOGE("RSSurfaceCaptureTaskParallel::Run: create capture task failed!");
318             return false;
319         }
320         RSBackgroundThread::Instance().PostTask(copytask);
321         return true;
322     } else {
323         std::shared_ptr<Drawing::Image> img(surface.get()->GetImageSnapshot());
324         if (!img) {
325             RS_LOGE("RSSurfaceCaptureTaskParallel::Run: img is nullptr");
326             return false;
327         }
328         if (!CopyDataToPixelMap(img, pixelMap_)) {
329             RS_LOGE("RSSurfaceCaptureTaskParallel::Run: CopyDataToPixelMap failed");
330             return false;
331         }
332     }
333 #endif
334     if (finalRotationAngle_) {
335         pixelMap_->rotate(finalRotationAngle_);
336     }
337     // To get dump image
338     // execute "param set rosen.dumpsurfacetype.enabled 3 && setenforce 0"
339     RSBaseRenderUtil::WritePixelMapToPng(*pixelMap_);
340     RS_LOGD("RSSurfaceCaptureTaskParallel::Run CaptureTask make a pixleMap with colorSpaceName: %{public}d",
341         pixelMap_->InnerGetGrColorSpace().GetColorSpaceName());
342     callback->OnSurfaceCapture(nodeId_, captureConfig_, pixelMap_.get());
343     return true;
344 }
345 
DrawHDRSurfaceContent(std::shared_ptr<Drawing::Surface> surface,bool isOnHDR,const RSSurfaceCaptureParam & captureParam)346 bool RSSurfaceCaptureTaskParallel::DrawHDRSurfaceContent(
347     std::shared_ptr<Drawing::Surface> surface, bool isOnHDR, const RSSurfaceCaptureParam& captureParam)
348 {
349     if (surface == nullptr) {
350         RS_LOGE("RSSurfaceCaptureTaskParallel::DrawHDRSurfaceContent surface is nullptr!");
351         return false;
352     }
353     RSPaintFilterCanvas canvas(surface.get());
354     canvas.Scale(captureConfig_.scaleX, captureConfig_.scaleY);
355     const Drawing::Rect& rect = captureConfig_.mainScreenRect;
356     if (rect.GetWidth() > 0 && rect.GetHeight() > 0) {
357         canvas.ClipRect({0, 0, rect.GetWidth(), rect.GetHeight()});
358         canvas.Translate(0 - rect.GetLeft(), 0 - rect.GetTop());
359     }
360     canvas.SetDisableFilterCache(true);
361     RSSurfaceRenderParams* curNodeParams = nullptr;
362     if (displayNodeDrawable_) {
363         RSPaintFilterCanvas::ScreenshotType type = isOnHDR ? RSPaintFilterCanvas::ScreenshotType::HDR_SCREENSHOT :
364             RSPaintFilterCanvas::ScreenshotType::SDR_SCREENSHOT;
365         CaptureDisplayNode(*displayNodeDrawable_, canvas, captureParam, type);
366     } else {
367         RS_LOGE("RSSurfaceCaptureTaskParallel::DrawHDRSurfaceContent: Invalid RSRenderNodeDrawable!");
368         return false;
369     }
370     RSUniRenderThread::ResetCaptureParam();
371 #if (defined(RS_ENABLE_GL) || defined(RS_ENABLE_VK)) && \
372     (defined(RS_ENABLE_EGLIMAGE) && defined(RS_ENABLE_UNI_RENDER))
373     RSUniRenderUtil::OptimizedFlushAndSubmit(surface, gpuContext_.get(), GetFeatureParamValue("CaptureConfig",
374         &CaptureBaseParam::IsSnapshotWithDMAEnabled).value_or(false));
375 #endif
376     return true;
377 }
378 
RunHDR(sptr<RSISurfaceCaptureCallback> callback,const RSSurfaceCaptureParam & captureParam)379 bool RSSurfaceCaptureTaskParallel::RunHDR(
380     sptr<RSISurfaceCaptureCallback> callback, const RSSurfaceCaptureParam& captureParam)
381 {
382     if (!UseScreenShotWithHDR() || !callback) {
383         RS_LOGE("RSSurfaceCaptureTaskParallel::RunHDR not HDR screenshot or callback is nullptr.");
384         return false;
385     }
386 #if defined(RS_ENABLE_GL) || defined(RS_ENABLE_VK)
387     SetupGpuContext();
388     std::string nodeName("RSSurfaceCaptureTaskParallel");
389     RSTagTracker tagTracker(gpuContext_, nodeId_, RSTagTracker::TAGTYPE::TAG_CAPTURE, nodeName);
390 #endif
391     auto surface = CreateSurface(pixelMap_);
392     auto surfaceHDR = CreateSurface(pixelMapHDR_);
393     if (!DrawHDRSurfaceContent(surface, false, captureParam) ||
394         !DrawHDRSurfaceContent(surfaceHDR, true, captureParam)) {
395         RS_LOGE("RSSurfaceCaptureTaskParallel::RunHDR: DrawHDRSurfaceContent failed!");
396         return false;
397     }
398 #if (defined(RS_ENABLE_GL) || defined(RS_ENABLE_VK)) && \
399     (defined(RS_ENABLE_EGLIMAGE) && defined(RS_ENABLE_UNI_RENDER))
400     bool snapshotDmaEnabled = system::GetBoolParameter("rosen.snapshotDma.enabled", true);
401     bool isEnableFeature = GetFeatureParamValue("CaptureConfig",
402         &CaptureBaseParam::IsSnapshotWithDMAEnabled).value_or(false);
403     if (snapshotDmaEnabled && isEnableFeature) {
404         auto copytask = CreateSurfaceSyncCopyTaskWithDoublePixelMap(surface, std::move(pixelMap_),
405             surfaceHDR, std::move(pixelMapHDR_), nodeId_, captureConfig_, callback, finalRotationAngle_);
406         if (!copytask) {
407             RS_LOGE("RSSurfaceCaptureTaskParallel::RunHDR: create capture task failed!");
408             return false;
409         }
410         RSBackgroundThread::Instance().PostTask(copytask);
411         return true;
412     } else {
413         std::shared_ptr<Drawing::Image> img(surface.get()->GetImageSnapshot());
414         std::shared_ptr<Drawing::Image> imgHDR(surfaceHDR.get()->GetImageSnapshot());
415         if (!img || !imgHDR) {
416             RS_LOGE("RSSurfaceCaptureTaskParallel::RunHDR: img or imgHDR is nullptr");
417             return false;
418         }
419         if (!CopyDataToPixelMap(img, pixelMap_) || !CopyDataToPixelMap(imgHDR, pixelMapHDR_)) {
420             RS_LOGE("RSSurfaceCaptureTaskParallel::RunHDR: CopyDataToPixelMap failed");
421             return false;
422         }
423     }
424 #endif
425     if (finalRotationAngle_) {
426         pixelMap_->rotate(finalRotationAngle_);
427         pixelMapHDR_->rotate(finalRotationAngle_);
428     }
429     // To get dump image
430     // execute "param set rosen.dumpsurfacetype.enabled 3 && setenforce 0"
431     RSBaseRenderUtil::WritePixelMapToPng(*pixelMap_);
432     RSBaseRenderUtil::WritePixelMapToPng(*pixelMapHDR_);
433     RS_LOGD("RSSurfaceCaptureTaskParallel::RunHDR CaptureTask make pixleMaps with colorSpaceName:"
434         " %{public}d and %{public}d", pixelMap_->InnerGetGrColorSpace().GetColorSpaceName(),
435         pixelMapHDR_->InnerGetGrColorSpace().GetColorSpaceName());
436     callback->OnSurfaceCapture(nodeId_, captureConfig_, pixelMap_.get(), pixelMapHDR_.get());
437     return true;
438 }
439 
CreatePixelMapBySurfaceNode(std::shared_ptr<RSSurfaceRenderNode> node,bool isF16Capture)440 std::unique_ptr<Media::PixelMap> RSSurfaceCaptureTaskParallel::CreatePixelMapBySurfaceNode(
441     std::shared_ptr<RSSurfaceRenderNode> node, bool isF16Capture)
442 {
443     if (node == nullptr) {
444         RS_LOGE("RSSurfaceCaptureTaskParallel::CreatePixelMapBySurfaceNode: node == nullptr");
445         return nullptr;
446     }
447     int pixmapWidth = node->GetRenderProperties().GetBoundsWidth();
448     int pixmapHeight = node->GetRenderProperties().GetBoundsHeight();
449 
450     Media::InitializationOptions opts;
451     if (isF16Capture) {
452         opts.pixelFormat = Media::PixelFormat::RGBA_F16;
453     }
454     opts.size.width = ceil(pixmapWidth * captureConfig_.scaleX);
455     opts.size.height = ceil(pixmapHeight * captureConfig_.scaleY);
456     // Surface Node currently does not support regional screenshot
457     captureConfig_.mainScreenRect = {};
458     RS_LOGI("RSSurfaceCaptureTaskParallel::CreatePixelMapBySurfaceNode: NodeId:[%{public}" PRIu64 "],"
459         " origin pixelmap size: [%{public}u, %{public}u],"
460         " scale: [%{public}f, %{public}f],"
461         " useDma: [%{public}d], useCurWindow: [%{public}d],"
462         " isOnTheTree: [%{public}d], isVisible: [%{public}d],"
463         " backGroundColor: [%{public}d], isF16Capture: [%{public}d]",
464         node->GetId(), pixmapWidth, pixmapHeight, captureConfig_.scaleX, captureConfig_.scaleY,
465         captureConfig_.useDma, captureConfig_.useCurWindow, node->IsOnTheTree(),
466         !surfaceNode_->GetVisibleRegion().IsEmpty(), captureConfig_.backGroundColor, isF16Capture);
467     std::unique_ptr<Media::PixelMap> pixelMap = Media::PixelMap::Create(opts);
468     if (pixelMap) {
469         GraphicColorGamut windowColorGamut = GraphicColorGamut::GRAPHIC_COLOR_GAMUT_SRGB;
470         if (!isF16Capture) {
471             windowColorGamut = node->IsLeashWindow() ? node->GetFirstLevelNodeColorGamut() : node->GetColorSpace();
472         }
473         pixelMap->InnerSetColorSpace(windowColorGamut == GraphicColorGamut::GRAPHIC_COLOR_GAMUT_SRGB ?
474             OHOS::ColorManager::ColorSpace(OHOS::ColorManager::ColorSpaceName::SRGB) :
475             OHOS::ColorManager::ColorSpace(OHOS::ColorManager::ColorSpaceName::DISPLAY_P3));
476     }
477     return pixelMap;
478 }
479 
CreatePixelMapByDisplayNode(std::shared_ptr<RSLogicalDisplayRenderNode> node,bool isHDRCapture)480 std::unique_ptr<Media::PixelMap> RSSurfaceCaptureTaskParallel::CreatePixelMapByDisplayNode(
481     std::shared_ptr<RSLogicalDisplayRenderNode> node, bool isHDRCapture)
482 {
483     if (node == nullptr) {
484         RS_LOGE("RSSurfaceCaptureTaskParallel::CreatePixelMapByDisplayNode: node is nullptr");
485         return nullptr;
486     }
487     uint64_t screenId = node->GetScreenId();
488     sptr<RSScreenManager> screenManager = CreateOrGetScreenManager();
489     if (!screenManager) {
490         RS_LOGE("RSSurfaceCaptureTaskParallel::CreatePixelMapByDisplayNode: screenManager is nullptr!");
491         return nullptr;
492     }
493 
494     screenCorrection_ = screenManager->GetScreenCorrection(screenId);
495     screenRotation_ = node->GetScreenRotation();
496     finalRotationAngle_ = CalPixelMapRotation();
497     auto bounds = node->GetRenderProperties().GetBoundsGeometry();
498     uint32_t pixmapWidth = static_cast<uint32_t>(bounds->GetWidth());
499     uint32_t pixmapHeight = static_cast<uint32_t>(bounds->GetHeight());
500     boundsX_ = bounds->GetX();
501     boundsY_ = bounds->GetY();
502     auto rotation = node->GetRotation();
503     if (rotation == ScreenRotation::ROTATION_90 || rotation == ScreenRotation::ROTATION_270) {
504         std::swap(pixmapWidth, pixmapHeight);
505     }
506 
507     const Drawing::Rect& rect = captureConfig_.mainScreenRect;
508     float rectWidth = rect.GetWidth();
509     float rectHeight = rect.GetHeight();
510     if (rectWidth > 0 && rectHeight > 0 && rectWidth <= pixmapWidth && rectHeight <= pixmapHeight) {
511         pixmapWidth = floor(rectWidth);
512         pixmapHeight = floor(rectHeight);
513     }
514 
515     Media::InitializationOptions opts;
516     if (isHDRCapture) {
517         opts.pixelFormat = Media::PixelFormat::RGBA_F16;
518     }
519     opts.size.width = ceil(pixmapWidth * captureConfig_.scaleX);
520     opts.size.height = ceil(pixmapHeight * captureConfig_.scaleY);
521     RS_LOGI("RSSurfaceCaptureTaskParallel::%{public}s NodeId[%{public}" PRIu64 "],pixelmap[%{public}u, %{public}u],"
522         " scale[%{public}f, %{public}f], rect[%{public}f, %{public}f, %{public}f, %{public}f], dma[%{public}d],"
523         " rotation[%{public}d], correction[%{public}d], blackList[%{public}zu], isHDRCapture[%{public}d]", __func__,
524         node->GetId(), pixmapWidth, pixmapHeight, captureConfig_.scaleX, captureConfig_.scaleY,
525         rect.GetLeft(), rect.GetTop(), rect.GetWidth(), rect.GetHeight(), captureConfig_.useDma, screenRotation_,
526         screenCorrection_, captureConfig_.blackList.size(), isHDRCapture);
527     std::unique_ptr<Media::PixelMap> pixelMap = Media::PixelMap::Create(opts);
528     auto screenNode = std::static_pointer_cast<RSScreenRenderNode>(node->GetParent().lock());
529     if (pixelMap && screenNode) {
530         GraphicColorGamut windowColorGamut = isHDRCapture ?
531             GraphicColorGamut::GRAPHIC_COLOR_GAMUT_SRGB : screenNode->GetColorSpace();
532         pixelMap->InnerSetColorSpace(windowColorGamut == GraphicColorGamut::GRAPHIC_COLOR_GAMUT_SRGB ?
533             OHOS::ColorManager::ColorSpace(OHOS::ColorManager::ColorSpaceName::SRGB) :
534             OHOS::ColorManager::ColorSpace(OHOS::ColorManager::ColorSpaceName::DISPLAY_P3));
535     }
536     return pixelMap;
537 }
538 
CreateSurface(const std::unique_ptr<Media::PixelMap> & pixelmap)539 std::shared_ptr<Drawing::Surface> RSSurfaceCaptureTaskParallel::CreateSurface(
540     const std::unique_ptr<Media::PixelMap>& pixelmap)
541 {
542     if (pixelmap == nullptr) {
543         RS_LOGE("RSSurfaceCaptureTaskParallel::CreateSurface: pixelmap == nullptr");
544         return nullptr;
545     }
546     auto address = const_cast<uint8_t*>(pixelmap->GetPixels());
547     if (address == nullptr) {
548         RS_LOGE("RSSurfaceCaptureTaskParallel::CreateSurface: address == nullptr");
549         return nullptr;
550     }
551     OHOS::ColorManager::ColorSpaceName colorSpaceName = pixelmap->InnerGetGrColorSpace().GetColorSpaceName();
552     auto colorSpace = RSBaseRenderEngine::ConvertColorSpaceNameToDrawingColorSpace(colorSpaceName);
553     auto colorType = pixelmap->GetPixelFormat() == Media::PixelFormat::RGBA_F16 ?
554         Drawing::ColorType::COLORTYPE_RGBA_F16 :
555         Drawing::ColorType::COLORTYPE_RGBA_8888;
556     Drawing::ImageInfo info = Drawing::ImageInfo{pixelmap->GetWidth(), pixelmap->GetHeight(),
557         colorType, Drawing::AlphaType::ALPHATYPE_PREMUL, colorSpace};
558 
559 #if (defined(RS_ENABLE_GL) && defined(RS_ENABLE_EGLIMAGE))
560     if (RSSystemProperties::GetGpuApiType() == GpuApiType::OPENGL) {
561         auto renderEngine = RSUniRenderThread::Instance().GetRenderEngine();
562         if (renderEngine == nullptr) {
563             RS_LOGE("RSSurfaceCaptureTaskParallel::CreateSurface: renderEngine is nullptr");
564             return nullptr;
565         }
566 #if (defined(RS_ENABLE_GPU) && (defined(RS_ENABLE_GL) || defined(RS_ENABLE_VK)))
567         auto renderContext = renderEngine->GetRenderContext();
568 #else
569         auto renderContext = nullptr;
570 #endif
571         if (renderContext == nullptr) {
572             RS_LOGE("RSSurfaceCaptureTaskParallel::CreateSurface: renderContext is nullptr");
573             return nullptr;
574         }
575         renderContext->SetUpGpuContext(nullptr);
576         return Drawing::Surface::MakeRenderTarget(renderContext->GetDrGPUContext(), false, info);
577     }
578 #endif
579 #ifdef RS_ENABLE_VK
580     if (RSSystemProperties::GetGpuApiType() == GpuApiType::VULKAN ||
581         RSSystemProperties::GetGpuApiType() == GpuApiType::DDGR) {
582         return Drawing::Surface::MakeRenderTarget(gpuContext_.get(), false, info);
583     }
584 #endif
585 
586     return Drawing::Surface::MakeRasterDirect(info, address, pixelmap->GetRowBytes());
587 }
588 
589 #ifdef RS_ENABLE_GPU
SetupGpuContext()590 void RSSurfaceCaptureTaskParallel::SetupGpuContext()
591 {
592     auto renderEngine = RSUniRenderThread::Instance().GetRenderEngine();
593     if (renderEngine == nullptr) {
594         RS_LOGE("RSSurfaceCaptureTaskParallel::SetupGpuContext: renderEngine is nullptr");
595         return;
596     }
597     auto renderContext = renderEngine->GetRenderContext();
598     gpuContext_ = renderContext != nullptr ? renderContext->GetSharedDrGPUContext() : nullptr;
599     if (gpuContext_ == nullptr) {
600         RS_LOGW("RSSurfaceCaptureTaskParallel::SetupGpuContext gpuContext_ is nullptr");
601     }
602 }
603 #endif
604 
CalPixelMapRotation()605 int32_t RSSurfaceCaptureTaskParallel::CalPixelMapRotation()
606 {
607     auto screenRotation = ScreenRotationMapping(screenRotation_);
608     auto screenCorrection = ScreenRotationMapping(screenCorrection_);
609     int32_t rotation = screenRotation - screenCorrection;
610     return rotation;
611 }
612 
AddBlur(RSPaintFilterCanvas & canvas,const std::shared_ptr<Drawing::Surface> & surface,float blurRadius)613 void RSSurfaceCaptureTaskParallel::AddBlur(
614     RSPaintFilterCanvas& canvas, const std::shared_ptr<Drawing::Surface>& surface, float blurRadius)
615 {
616     Drawing::AutoCanvasRestore autoRestore(canvas, true);
617     canvas.ResetMatrix();
618     auto image = surface->GetImageSnapshot();
619     if (!image) {
620         RS_LOGE("RSSurfaceCaptureTaskParallel::AddBlur image is null");
621         return;
622     }
623     auto hpsParam = Drawing::HpsBlurParameter(Drawing::Rect(0, 0, image->GetWidth(), image->GetHeight()),
624         Drawing::Rect(0, 0, image->GetWidth(), image->GetHeight()), blurRadius, 1.f, 1.f);
625     auto filter = HpsBlurFilter::GetHpsBlurFilter();
626     filter.ApplyHpsBlur(canvas, image, hpsParam, 1.f);
627 }
628 
629 #ifdef RS_ENABLE_UNI_RENDER
CreateSurfaceSyncCopyTask(std::shared_ptr<Drawing::Surface> surface,std::unique_ptr<Media::PixelMap> pixelMap,NodeId id,const RSSurfaceCaptureConfig & captureConfig,sptr<RSISurfaceCaptureCallback> callback,int32_t rotation)630     std::function<void()> RSSurfaceCaptureTaskParallel::CreateSurfaceSyncCopyTask(
631         std::shared_ptr<Drawing::Surface> surface, std::unique_ptr<Media::PixelMap> pixelMap, NodeId id,
632         const RSSurfaceCaptureConfig& captureConfig, sptr<RSISurfaceCaptureCallback> callback,
633         int32_t rotation)
634 {
635     if (surface == nullptr) {
636         RS_LOGE("RSSurfaceCaptureTaskParallel: nodeId:[%{public}" PRIu64 "], surface is nullptr", id);
637         return {};
638     }
639     Drawing::BackendTexture backendTexture = surface->GetBackendTexture();
640     if (!backendTexture.IsValid()) {
641         RS_LOGE("RSSurfaceCaptureTaskParallel: SkiaSurface bind Image failed: BackendTexture is invalid");
642         return {};
643     }
644     auto wrapper = std::make_shared<std::tuple<std::unique_ptr<Media::PixelMap>>>();
645     std::get<0>(*wrapper) = std::move(pixelMap);
646     auto wrapperSf = std::make_shared<std::tuple<std::shared_ptr<Drawing::Surface>>>();
647     std::get<0>(*wrapperSf) = std::move(surface);
648     std::function<void()> copytask = [wrapper, captureConfig, callback, backendTexture, wrapperSf, id,
649         rotation]() -> void {
650         RS_TRACE_NAME_FMT("copy and send capture useDma:%d", captureConfig.useDma);
651         if (callback == nullptr) {
652             RS_LOGE("RSSurfaceCaptureTaskParallel: nodeId:[%{public}" PRIu64 "], callback is nullptr", id);
653             return;
654         }
655         auto surfaceInfo = std::get<0>(*wrapperSf)->GetImageInfo();
656         if (!backendTexture.IsValid()) {
657             RS_LOGE("RSSurfaceCaptureTaskParallel: Surface bind Image failed: BackendTexture is invalid");
658             callback->OnSurfaceCapture(id, captureConfig, nullptr);
659             RSUniRenderUtil::ClearNodeCacheSurface(
660                 std::move(std::get<0>(*wrapperSf)), nullptr, UNI_MAIN_THREAD_INDEX, 0);
661             return;
662         }
663         auto pixelmap = std::move(std::get<0>(*wrapper));
664         if (pixelmap == nullptr) {
665             RS_LOGE("RSSurfaceCaptureTaskParallel: pixelmap == nullptr");
666             callback->OnSurfaceCapture(id, captureConfig, nullptr);
667             RSUniRenderUtil::ClearNodeCacheSurface(
668                 std::move(std::get<0>(*wrapperSf)), nullptr, UNI_MAIN_THREAD_INDEX, 0);
669             return;
670         }
671 
672         if (!PixelMapCopy(pixelmap, surfaceInfo.GetColorSpace(), backendTexture, surfaceInfo.GetColorType(),
673             captureConfig.useDma, rotation)) {
674             callback->OnSurfaceCapture(id, captureConfig, nullptr);
675             RSUniRenderUtil::ClearNodeCacheSurface(
676                 std::move(std::get<0>(*wrapperSf)), nullptr, UNI_MAIN_THREAD_INDEX, 0);
677             return;
678         }
679         callback->OnSurfaceCapture(id, captureConfig, pixelmap.get());
680         RS_LOGI("RSSurfaceCaptureTaskParallel::Capture capture success nodeId:[%{public}]" PRIu64
681             "], pixelMap width: %{public}d, height: %{public}d",
682             id, pixelmap->GetWidth(), pixelmap->GetHeight());
683         RSBackgroundThread::Instance().CleanGrResource();
684         RSUniRenderUtil::ClearNodeCacheSurface(
685             std::move(std::get<0>(*wrapperSf)), nullptr, UNI_MAIN_THREAD_INDEX, 0);
686     };
687     return copytask;
688 }
689 
690 
CreateSurfaceSyncCopyTaskWithDoublePixelMap(std::shared_ptr<Drawing::Surface> surface,std::unique_ptr<Media::PixelMap> pixelMap,std::shared_ptr<Drawing::Surface> surfaceHDR,std::unique_ptr<Media::PixelMap> pixelMapHDR,NodeId id,const RSSurfaceCaptureConfig & captureConfig,sptr<RSISurfaceCaptureCallback> callback,int32_t rotation)691 std::function<void()> RSSurfaceCaptureTaskParallel::CreateSurfaceSyncCopyTaskWithDoublePixelMap(
692     std::shared_ptr<Drawing::Surface> surface, std::unique_ptr<Media::PixelMap> pixelMap,
693     std::shared_ptr<Drawing::Surface> surfaceHDR, std::unique_ptr<Media::PixelMap> pixelMapHDR, NodeId id,
694     const RSSurfaceCaptureConfig& captureConfig, sptr<RSISurfaceCaptureCallback> callback, int32_t rotation)
695 {
696     if (surface == nullptr || surfaceHDR == nullptr) {
697         RS_LOGE("RSSurfaceCaptureTaskParallel: nodeId:[%{public}" PRIu64 "], surface is nullptr", id);
698         return {};
699     }
700     Drawing::BackendTexture backendTexture = surface->GetBackendTexture();
701     Drawing::BackendTexture backendTextureHDR = surfaceHDR->GetBackendTexture();
702     if (!backendTexture.IsValid() || !backendTextureHDR.IsValid()) {
703         RS_LOGE("RSSurfaceCaptureTaskParallel: SkiaSurface bind Image failed: BackendTexture is invalid");
704         return {};
705     }
706     auto wrapper = std::make_shared<std::tuple<std::unique_ptr<Media::PixelMap>, std::unique_ptr<Media::PixelMap>>>();
707     std::get<0>(*wrapper) = std::move(pixelMap);
708     std::get<1>(*wrapper) = std::move(pixelMapHDR);
709     auto wrapperSf =
710         std::make_shared<std::tuple<std::shared_ptr<Drawing::Surface>, std::shared_ptr<Drawing::Surface>>>();
711     std::get<0>(*wrapperSf) = std::move(surface);
712     std::get<1>(*wrapperSf) = std::move(surfaceHDR);
713     std::function<void()> copytask = [wrapper, captureConfig, callback, backendTexture, backendTextureHDR, wrapperSf,
714         id, rotation]() -> void {
715         RS_TRACE_NAME_FMT("copy and send capture useDma:%d", captureConfig.useDma);
716         if (callback == nullptr) {
717             RS_LOGE("RSSurfaceCaptureTaskParallel: nodeId:[%{public}" PRIu64 "], callback is nullptr", id);
718             return;
719         }
720         auto surfaceInfo = std::get<0>(*wrapperSf)->GetImageInfo();
721         auto surfaceInfoHDR = std::get<1>(*wrapperSf)->GetImageInfo();
722         auto pixelmap = std::move(std::get<0>(*wrapper));
723         auto pixelmapHDR = std::move(std::get<1>(*wrapper));
724         if (pixelmap == nullptr || pixelmapHDR == nullptr) {
725             RS_LOGE("RSSurfaceCaptureTaskParallel: pixelmap or pixelmapHDR is nullptr");
726             callback->OnSurfaceCapture(id, captureConfig, nullptr, nullptr);
727             RSUniRenderUtil::ClearNodeCacheSurface(
728                 std::move(std::get<0>(*wrapperSf)), nullptr, UNI_MAIN_THREAD_INDEX, 0);
729             RSUniRenderUtil::ClearNodeCacheSurface(
730                 std::move(std::get<1>(*wrapperSf)), nullptr, UNI_MAIN_THREAD_INDEX, 0);
731                 return;
732         }
733         if (!PixelMapCopy(pixelmap, surfaceInfo.GetColorSpace(), backendTexture, surfaceInfo.GetColorType(),
734             captureConfig.useDma, rotation) ||
735             !PixelMapCopy(pixelmapHDR, surfaceInfoHDR.GetColorSpace(), backendTextureHDR, surfaceInfoHDR.GetColorType(),
736             captureConfig.useDma, rotation)) {
737             callback->OnSurfaceCapture(id, captureConfig, nullptr, nullptr);
738             RSUniRenderUtil::ClearNodeCacheSurface(
739                 std::move(std::get<0>(*wrapperSf)), nullptr, UNI_MAIN_THREAD_INDEX, 0);
740             RSUniRenderUtil::ClearNodeCacheSurface(
741                 std::move(std::get<1>(*wrapperSf)), nullptr, UNI_MAIN_THREAD_INDEX, 0);
742             return;
743         }
744 #ifdef USE_VIDEO_PROCESSING_ENGINE
745         GSError ret = RSHdrUtil::SetMetadata(reinterpret_cast<SurfaceBuffer*>(pixelmap->GetFd()),
746             RSHDRUtilConst::HDR_CAPTURE_SDR_COLORSPACE,
747             HDI::Display::Graphic::Common::V1_0::CM_HDR_Metadata_Type::CM_IMAGE_HDR_VIVID_DUAL);
748         if (ret != GSERROR_OK) {
749             RS_LOGE("RSSurfaceCaptureTaskParallel: Set SDR metadata error with: %{public}d", ret);
750             return;
751         }
752         ret = RSHdrUtil::SetMetadata(reinterpret_cast<SurfaceBuffer*>(pixelmapHDR->GetFd()),
753             RSHDRUtilConst::HDR_CAPTURE_HDR_COLORSPACE,
754             HDI::Display::Graphic::Common::V1_0::CM_HDR_Metadata_Type::CM_IMAGE_HDR_VIVID_SINGLE);
755         if (ret != GSERROR_OK) {
756             RS_LOGE("RSSurfaceCaptureTaskParallel: Set HDR metadata error with: %{public}d", ret);
757             return;
758         }
759 #endif
760         callback->OnSurfaceCapture(id, captureConfig, pixelmap.get(), pixelmapHDR.get());
761         RSBackgroundThread::Instance().CleanGrResource();
762         RSUniRenderUtil::ClearNodeCacheSurface(
763             std::move(std::get<0>(*wrapperSf)), nullptr, UNI_MAIN_THREAD_INDEX, 0);
764         RSUniRenderUtil::ClearNodeCacheSurface(
765             std::move(std::get<1>(*wrapperSf)), nullptr, UNI_MAIN_THREAD_INDEX, 0);
766     };
767     return copytask;
768 }
769 
PixelMapCopy(std::unique_ptr<Media::PixelMap> & pixelmap,std::shared_ptr<Drawing::ColorSpace> colorSpace,const Drawing::BackendTexture & backendTexture,Drawing::ColorType colorType,bool useDma,int32_t rotation)770 bool RSSurfaceCaptureTaskParallel::PixelMapCopy(std::unique_ptr<Media::PixelMap>& pixelmap,
771     std::shared_ptr<Drawing::ColorSpace> colorSpace, const Drawing::BackendTexture& backendTexture,
772     Drawing::ColorType colorType, bool useDma, int32_t rotation)
773 {
774     if (!pixelmap) {
775         return false;
776     }
777     Drawing::ImageInfo info = Drawing::ImageInfo{ pixelmap->GetWidth(), pixelmap->GetHeight(),
778         colorType, Drawing::ALPHATYPE_PREMUL, colorSpace};
779     Drawing::TextureOrigin textureOrigin = Drawing::TextureOrigin::BOTTOM_LEFT;
780     Drawing::BitmapFormat bitmapFormat =
781         Drawing::BitmapFormat{ colorType, Drawing::ALPHATYPE_PREMUL };
782     std::shared_ptr<Drawing::Surface> surface;
783     auto grContext = RSBackgroundThread::Instance().GetShareGPUContext();
784     if (!grContext) {
785         RS_LOGE("RSSurfaceCaptureTaskParallel: GetShareGPUContext fail.");
786         return false;
787     }
788 #if defined(ROSEN_OHOS) && defined(RS_ENABLE_VK)
789     DmaMem dmaMem;
790     if (useDma &&
791         (RSSystemProperties::GetGpuApiType() == GpuApiType::VULKAN ||
792         RSSystemProperties::GetGpuApiType() == GpuApiType::DDGR)) {
793         sptr<SurfaceBuffer> surfaceBuffer = dmaMem.DmaMemAlloc(info, pixelmap);
794         if (surfaceBuffer != nullptr && colorSpace != nullptr && !colorSpace->IsSRGB()) {
795             surfaceBuffer->SetSurfaceBufferColorGamut(GraphicColorGamut::GRAPHIC_COLOR_GAMUT_DISPLAY_P3);
796         }
797         surface = dmaMem.GetSurfaceFromSurfaceBuffer(surfaceBuffer, grContext);
798         if (surface == nullptr) {
799             RS_LOGE("RSSurfaceCaptureTaskParallel: GetSurfaceFromSurfaceBuffer fail.");
800             return false;
801         }
802         auto tmpImg = std::make_shared<Drawing::Image>();
803         DrawCapturedImg(*tmpImg, *surface, backendTexture, textureOrigin, bitmapFormat);
804     } else {
805 #else
806     {
807 #endif
808         auto tmpImg = std::make_shared<Drawing::Image>();
809         tmpImg->BuildFromTexture(*grContext, backendTexture.GetTextureInfo(),
810             textureOrigin, bitmapFormat, colorSpace);
811         if (!CopyDataToPixelMap(tmpImg, pixelmap)) {
812             RS_LOGE("RSSurfaceCaptureTaskParallel: CopyDataToPixelMap failed");
813             return false;
814         }
815     }
816     if (rotation) {
817         pixelmap->rotate(rotation);
818     }
819 
820     RSUniRenderUtil::FlushDmaSurfaceBuffer(pixelmap.get());
821     //To get dump image
822     // execute "param set rosen.dumpsurfacetype.enabled 3 && setenforce 0"
823     RSBaseRenderUtil::WritePixelMapToPng(*pixelmap);
824     auto pixelDump = PixelMapSamplingDump(pixelmap, pixelmap->GetWidth() / 2, 0) |
825                     PixelMapSamplingDump(pixelmap, 0, pixelmap->GetHeight() / 2) |
826                     PixelMapSamplingDump(pixelmap, pixelmap->GetWidth() / 2, pixelmap->GetHeight() / 2) |
827                     PixelMapSamplingDump(pixelmap, pixelmap->GetWidth() - 1, pixelmap->GetHeight() / 2) |
828                     PixelMapSamplingDump(pixelmap, pixelmap->GetWidth() / 2, pixelmap->GetHeight() - 1);
829     if ((pixelDump & ALPHA_MASK) != 0) {
830         RS_LOGI("RSSurfaceCaptureTaskParallel::PixelMapCopy pixelmap is Non-transparent");
831     } else {
832         RS_LOGW("RSSurfaceCaptureTaskParallel::PixelMapCopy pixelmap is transparent");
833     }
834     pixelmap->SetMemoryName("RSSurfaceCaptureForClient");
835     return true;
836 }
837 #endif // RS_ENABLE_UNI_RENDER
838 
839 void RSSurfaceCaptureTaskParallel::CaptureDisplayNode(DrawableV2::RSRenderNodeDrawable& displayNodeDrawable,
840     RSPaintFilterCanvas& canvas, const RSSurfaceCaptureParam& captureParam, RSPaintFilterCanvas::ScreenshotType type)
841 {
842     bool secExemption = false;
843     auto& uniParams = RSUniRenderThread::Instance().GetRSRenderThreadParams();
844     if (uniParams) {
845         secExemption = uniParams->GetSecExemption();
846         uniParams->SetSecExemption(captureParam.secExemption || secExemption);
847     }
848     RSUniRenderThread::SetCaptureParam(CaptureParam(true, false, false));
849     canvas.SetScreenshotType(type);
850     // Screenshot blacklist, exclude surfaceNode in blacklist while capturing displaynode
851     std::unordered_set<NodeId> blackList(captureConfig_.blackList.begin(), captureConfig_.blackList.end());
852     RSUniRenderThread::Instance().SetBlackList(blackList);
853     displayNodeDrawable.OnCapture(canvas);
854     RSUniRenderThread::Instance().SetBlackList({});
855     if (uniParams) {
856         uniParams->SetSecExemption(secExemption);
857     }
858 }
859 
860 #if defined(ROSEN_OHOS) && defined(RS_ENABLE_VK)
861 DmaMem::~DmaMem()
862 {
863     ReleaseDmaMemory();
864 }
865 
866 void DmaMem::ReleaseDmaMemory()
867 {
868     if (nativeWindowBuffer_ != nullptr) {
869         DestroyNativeWindowBuffer(nativeWindowBuffer_);
870         nativeWindowBuffer_ = nullptr;
871     }
872 }
873 
874 sptr<SurfaceBuffer> DmaMem::DmaMemAlloc(Drawing::ImageInfo &dstInfo, const std::unique_ptr<Media::PixelMap>& pixelmap)
875 {
876 #if defined(_WIN32) || defined(_APPLE) || defined(A_PLATFORM) || defined(IOS_PLATFORM)
877     RS_LOGE("Unsupport dma mem alloc");
878     return nullptr;
879 #else
880     if (pixelmap == nullptr) {
881         RS_LOGE("DmaMem::DmaMemAlloc: pixelmap is nullptr");
882         return nullptr;
883     }
884     sptr<SurfaceBuffer> surfaceBuffer = SurfaceBuffer::Create();
885     if (!surfaceBuffer) {
886         RS_LOGE("DmaMem::DmaMemAlloc: surfaceBuffer create failed");
887         return nullptr;
888     }
889     auto colorGamut = pixelmap->InnerGetGrColorSpace().GetColorSpaceName() == OHOS::ColorManager::ColorSpaceName::SRGB ?
890         GraphicColorGamut::GRAPHIC_COLOR_GAMUT_SRGB : GraphicColorGamut::GRAPHIC_COLOR_GAMUT_DISPLAY_P3;
891     BufferRequestConfig requestConfig = {
892         .width = dstInfo.GetWidth(),
893         .height = dstInfo.GetHeight(),
894         .strideAlignment = 0x8, // set 0x8 as default value to alloc SurfaceBufferImpl
895         .format = dstInfo.GetColorType() == Drawing::ColorType::COLORTYPE_RGBA_F16 ?
896             GRAPHIC_PIXEL_FMT_RGBA16_FLOAT : GRAPHIC_PIXEL_FMT_RGBA_8888, // PixelFormat
897         .usage = BUFFER_USAGE_CPU_READ | BUFFER_USAGE_HW_RENDER | BUFFER_USAGE_HW_TEXTURE |
898             BUFFER_USAGE_MEM_DMA | BUFFER_USAGE_MEM_MMZ_CACHE,
899         .timeout = 0,
900         .colorGamut = colorGamut,
901         .transform = GraphicTransformType::GRAPHIC_ROTATE_NONE,
902     };
903     GSError ret = surfaceBuffer->Alloc(requestConfig);
904     if (ret != GSERROR_OK) {
905         RS_LOGE("DmaMem::DmaMemAlloc: surfaceBuffer alloc failed, %{public}s", GSErrorStr(ret).c_str());
906         return nullptr;
907     }
908     void* nativeBuffer = surfaceBuffer.GetRefPtr();
909     OHOS::RefBase *ref = reinterpret_cast<OHOS::RefBase *>(nativeBuffer);
910     ref->IncStrongRef(ref);
911     int32_t bufferSize = pixelmap->GetByteCount();
912     pixelmap->SetPixelsAddr(surfaceBuffer->GetVirAddr(), nativeBuffer, bufferSize,
913         Media::AllocatorType::DMA_ALLOC, nullptr);
914     return surfaceBuffer;
915 #endif
916 }
917 
918 static inline void DeleteVkImage(void *context)
919 {
920     NativeBufferUtils::VulkanCleanupHelper *cleanupHelper =
921         static_cast<NativeBufferUtils::VulkanCleanupHelper *> (context);
922     if (cleanupHelper != nullptr) {
923         cleanupHelper->UnRef();
924     }
925 }
926 
927 std::shared_ptr<Drawing::Surface> DmaMem::GetSurfaceFromSurfaceBuffer(
928     sptr<SurfaceBuffer> surfaceBuffer, std::shared_ptr<Drawing::GPUContext> gpuContext)
929 {
930     if (surfaceBuffer == nullptr || gpuContext == nullptr) {
931         RS_LOGE("GetSurfaceFromSurfaceBuffer surfaceBuffer or gpuContext is nullptr");
932         return nullptr;
933     }
934     if (nativeWindowBuffer_ == nullptr) {
935         nativeWindowBuffer_ = CreateNativeWindowBufferFromSurfaceBuffer(&surfaceBuffer);
936         if (!nativeWindowBuffer_) {
937             RS_LOGE("DmaMem::GetSurfaceFromSurfaceBuffer: nativeWindowBuffer_ is nullptr");
938             return nullptr;
939         }
940     }
941 
942     Drawing::BackendTexture backendTextureTmp =
943         NativeBufferUtils::MakeBackendTextureFromNativeBuffer(nativeWindowBuffer_,
944             surfaceBuffer->GetWidth(), surfaceBuffer->GetHeight());
945     if (!backendTextureTmp.IsValid()) {
946         return nullptr;
947     }
948 
949     auto vkTextureInfo = backendTextureTmp.GetTextureInfo().GetVKTextureInfo();
950     if (vkTextureInfo == nullptr) {
951         return nullptr;
952     }
953     vkTextureInfo->imageUsageFlags = vkTextureInfo->imageUsageFlags | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
954     auto cleanUpHelper = new NativeBufferUtils::VulkanCleanupHelper(RsVulkanContext::GetSingleton(),
955         vkTextureInfo->vkImage, vkTextureInfo->vkAlloc.memory);
956     if (cleanUpHelper == nullptr) {
957         return nullptr;
958     }
959     // attention: cleanUpHelper will be delete by NativeBufferUtils::DeleteVkImage, don't delete again
960     auto colorSpace =
961         RSBaseRenderEngine::ConvertColorGamutToDrawingColorSpace(surfaceBuffer->GetSurfaceBufferColorGamut());
962     auto colorType = surfaceBuffer->GetBufferRequestConfig().format == GRAPHIC_PIXEL_FMT_RGBA16_FLOAT ?
963         Drawing::ColorType::COLORTYPE_RGBA_F16 : Drawing::ColorType::COLORTYPE_RGBA_8888;
964     auto drawingSurface = Drawing::Surface::MakeFromBackendTexture(
965         gpuContext.get(),
966         backendTextureTmp.GetTextureInfo(),
967         Drawing::TextureOrigin::TOP_LEFT,
968         1, colorType, colorSpace,
969         NativeBufferUtils::DeleteVkImage, cleanUpHelper);
970     return drawingSurface;
971 }
972 #endif
973 } // namespace Rosen
974 } // namespace OHOS
975