• 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_ui_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_surface_capture_task_parallel.h"
36 #include "pipeline/rs_uifirst_manager.h"
37 #include "pipeline/rs_uni_render_judgement.h"
38 #include "pipeline/rs_uni_render_util.h"
39 #include "platform/common/rs_log.h"
40 #include "platform/drawing/rs_surface.h"
41 #include "render/rs_drawing_filter.h"
42 #include "render/rs_skia_filter.h"
43 #include "screen_manager/rs_screen_manager.h"
44 #include "screen_manager/rs_screen_mode_info.h"
45 #include "drawable/rs_canvas_render_node_drawable.h"
46 #include "pipeline/rs_canvas_render_node.h"
47 
48 #ifdef RS_ENABLE_VK
49 #include "platform/ohos/backend/native_buffer_utils.h"
50 #endif
51 
52 namespace OHOS {
53 namespace Rosen {
54 
DrawCapturedImg(Drawing::Image & image,Drawing::Surface & surface,const Drawing::BackendTexture & backendTexture,Drawing::TextureOrigin & textureOrigin,Drawing::BitmapFormat & bitmapFormat)55 static inline void DrawCapturedImg(Drawing::Image& image,
56     Drawing::Surface& surface, const Drawing::BackendTexture& backendTexture,
57     Drawing::TextureOrigin& textureOrigin, Drawing::BitmapFormat& bitmapFormat)
58 {
59     RSPaintFilterCanvas canvas(&surface);
60     auto gpuContext = canvas.GetGPUContext();
61     if (gpuContext == nullptr) {
62         RS_LOGE("DrawCapturedImg failed: gpuContext is nullptr");
63         return;
64     }
65     image.BuildFromTexture(*gpuContext, backendTexture.GetTextureInfo(),
66         textureOrigin, bitmapFormat, nullptr);
67     canvas.DrawImage(image, 0.f, 0.f, Drawing::SamplingOptions());
68     surface.FlushAndSubmit(true);
69 }
70 
IsRectValid(NodeId nodeId,const Drawing::Rect & specifiedAreaRect)71 bool RSUiCaptureTaskParallel::IsRectValid(NodeId nodeId, const Drawing::Rect& specifiedAreaRect)
72 {
73     RS_LOGD("RSUiCaptureTaskParallel::IsRectValid: NodeId:[%{public}" PRIu64 "],"
74         " Rect Left is [%{public}f], Top is [%{public}f],"
75         " Right is [%{public}f], Bottom is [%{public}f],",
76         nodeId, specifiedAreaRect.GetLeft(), specifiedAreaRect.GetTop(),
77         specifiedAreaRect.GetRight(), specifiedAreaRect.GetBottom());
78     auto node = RSMainThread::Instance()->GetContext().GetNodeMap().GetRenderNode(nodeId);
79     if (node == nullptr) {
80         RS_LOGE("RSUiCaptureTaskParallel::IsRectValid: Invalid nodeId:[%{public}" PRIu64 "]", nodeId);
81         return false;
82     }
83     if (!specifiedAreaRect.IsValid()) {
84         RS_LOGD("RSUiCaptureTaskParallel::IsRectValid: specifiedAreaRect is an invalid rect");
85         return false;
86     }
87     if ((specifiedAreaRect.GetWidth() > node->GetRenderProperties().GetBoundsWidth()) ||
88         (specifiedAreaRect.GetHeight() > node->GetRenderProperties().GetBoundsHeight()) ||
89         (specifiedAreaRect.GetLeft() < 0) || (specifiedAreaRect.GetTop() < 0) ||
90         (specifiedAreaRect.GetRight() > node->GetRenderProperties().GetBoundsWidth()) ||
91         (specifiedAreaRect.GetBottom() > node->GetRenderProperties().GetBoundsHeight())) {
92         RS_LOGE("RSUiCaptureTaskParallel::IsRectValid: specifiedAreaRect is out of bounds");
93         return false;
94     }
95     return true;
96 }
97 
Capture(NodeId id,sptr<RSISurfaceCaptureCallback> callback,const RSSurfaceCaptureConfig & captureConfig,const Drawing::Rect & specifiedAreaRect)98 void RSUiCaptureTaskParallel::Capture(NodeId id, sptr<RSISurfaceCaptureCallback> callback,
99     const RSSurfaceCaptureConfig& captureConfig, const Drawing::Rect& specifiedAreaRect)
100 {
101     if (callback == nullptr) {
102         RS_LOGE("RSUiCaptureTaskParallel::Capture nodeId:[%{public}" PRIu64 "], callback is nullptr", id);
103         return;
104     }
105     RS_LOGI("RSUiCaptureTaskParallel::Capture nodeId:[%{public}" PRIu64 "]", id);
106     captureCount_++;
107     std::shared_ptr<RSUiCaptureTaskParallel> captureHandle =
108         std::make_shared<RSUiCaptureTaskParallel>(id, captureConfig);
109     if (captureHandle == nullptr) {
110         RS_LOGE("RSUiCaptureTaskParallel::Capture captureHandle is nullptr!");
111         ProcessUiCaptureCallback(callback, id, nullptr);
112         return;
113     }
114     if (!captureHandle->CreateResources(specifiedAreaRect)) {
115         RS_LOGE("RSUiCaptureTaskParallel::Capture CreateResources failed");
116         ProcessUiCaptureCallback(callback, id, nullptr);
117         return;
118     }
119     Drawing::Rect chosenRect;
120     Drawing::Rect invalidRect(0.f, 0.f, 0.f, 0.f);
121     if (!IsRectValid(id, specifiedAreaRect)) {
122         chosenRect = invalidRect;
123         RS_LOGD("RSUiCaptureTaskParallel::Capture invalid rect");
124     } else {
125         chosenRect = specifiedAreaRect;
126     }
127     std::function<void()> captureTask = [captureHandle, id, callback, chosenRect]() -> void {
128         RSSystemProperties::SetForceHpsBlurDisabled(true);
129         if (!captureHandle->Run(callback, chosenRect)) {
130             ProcessUiCaptureCallback(callback, id, nullptr);
131         }
132         RSSystemProperties::SetForceHpsBlurDisabled(false);
133     };
134     RSUniRenderThread::Instance().PostTask(captureTask);
135 }
136 
CreateResources(const Drawing::Rect & specifiedAreaRect)137 bool RSUiCaptureTaskParallel::CreateResources(const Drawing::Rect& specifiedAreaRect)
138 {
139     if (ROSEN_EQ(captureConfig_.scaleX, 0.f) || ROSEN_EQ(captureConfig_.scaleY, 0.f) ||
140         captureConfig_.scaleX < 0.f || captureConfig_.scaleY < 0.f) {
141         RS_LOGE("RSUiCaptureTaskParallel::CreateResources: SurfaceCapture scale is invalid.");
142         return false;
143     }
144     auto node = RSMainThread::Instance()->GetContext().GetNodeMap().GetRenderNode(nodeId_);
145     if (node == nullptr) {
146         RS_LOGE("RSUiCaptureTaskParallel::CreateResources: Invalid nodeId:[%{public}" PRIu64 "]",
147             nodeId_);
148         return false;
149     }
150 
151     if (node->GetType() != RSRenderNodeType::ROOT_NODE &&
152         node->GetType() != RSRenderNodeType::CANVAS_NODE &&
153         node->GetType() != RSRenderNodeType::CANVAS_DRAWING_NODE &&
154         node->GetType() != RSRenderNodeType::SURFACE_NODE) {
155         RS_LOGE("RSUiCaptureTaskParallel::CreateResources: Invalid RSRenderNodeType!");
156         return false;
157     }
158 #ifdef RS_ENABLE_VK
159     float nodeBoundsWidth = node->GetRenderProperties().GetBoundsWidth();
160     float nodeBoundsHeight = node->GetRenderProperties().GetBoundsHeight();
161     int32_t width = ceil(nodeBoundsWidth * captureConfig_.scaleX);
162     int32_t height = ceil(nodeBoundsHeight * captureConfig_.scaleY);
163     if (width * height > static_cast<int32_t>(OHOS::Rosen::NativeBufferUtils::VKIMAGE_LIMIT_SIZE)) {
164         RS_LOGE("RSUiCaptureTaskParallel::CreateResources: image is too large, width:%{public}d, height::%{public}d",
165             width, height);
166         return false;
167     }
168     RS_LOGD("RSUiCaptureTaskParallel::CreateResources: Origin nodeBoundsWidth is [%{public}f,]"
169         " Origin nodeBoundsHeight is [%{public}f]", nodeBoundsWidth, nodeBoundsHeight);
170 #endif
171     if (auto surfaceNode = node->ReinterpretCastTo<RSSurfaceRenderNode>()) {
172         // Determine whether cache can be used
173         auto curNode = surfaceNode;
174         auto parentNode = RSBaseRenderNode::ReinterpretCast<RSSurfaceRenderNode>(surfaceNode->GetParent().lock());
175         if (parentNode && parentNode->IsLeashWindow() && parentNode->ShouldPaint() &&
176             (parentNode->GetLastFrameUifirstFlag() == MultiThreadCacheType::LEASH_WINDOW ||
177             parentNode->GetLastFrameUifirstFlag() == MultiThreadCacheType::NONFOCUS_WINDOW)) {
178             curNode = parentNode;
179         }
180 
181         nodeDrawable_ = std::static_pointer_cast<DrawableV2::RSRenderNodeDrawable>(
182             DrawableV2::RSRenderNodeDrawableAdapter::OnGenerate(curNode));
183         if (IsRectValid(nodeId_, specifiedAreaRect)) {
184             pixelMap_ = CreatePixelMapByRect(specifiedAreaRect);
185         } else {
186             pixelMap_ = CreatePixelMapByNode(curNode);
187         }
188     } else if (auto canvasNode = node->ReinterpretCastTo<RSCanvasRenderNode>()) {
189         nodeDrawable_ = std::static_pointer_cast<DrawableV2::RSRenderNodeDrawable>(
190             DrawableV2::RSRenderNodeDrawableAdapter::OnGenerate(canvasNode));
191         if (IsRectValid(nodeId_, specifiedAreaRect)) {
192             pixelMap_ = CreatePixelMapByRect(specifiedAreaRect);
193         } else {
194             pixelMap_ = CreatePixelMapByNode(canvasNode);
195         }
196     } else {
197         RS_LOGE("RSUiCaptureTaskParallel::CreateResources: Invalid RSRenderNode!");
198         return false;
199     }
200     if (pixelMap_ == nullptr) {
201         RS_LOGE("RSUiCaptureTaskParallel::CreateResources: pixelMap_ is nullptr!");
202         return false;
203     }
204     return true;
205 }
206 
Run(sptr<RSISurfaceCaptureCallback> callback,const Drawing::Rect & specifiedAreaRect)207 bool RSUiCaptureTaskParallel::Run(sptr<RSISurfaceCaptureCallback> callback, const Drawing::Rect& specifiedAreaRect)
208 {
209     RS_TRACE_NAME("RSUiCaptureTaskParallel::TakeSurfaceCapture");
210 
211 #if defined(RS_ENABLE_GL) || defined(RS_ENABLE_VK)
212     auto renderContext = RSUniRenderThread::Instance().GetRenderEngine()->GetRenderContext();
213     auto grContext = renderContext != nullptr ? renderContext->GetDrGPUContext() : nullptr;
214     std::string nodeName("RSUiCaptureTaskParallel");
215     RSTagTracker tagTracker(grContext, nodeId_, RSTagTracker::TAGTYPE::TAG_CAPTURE, nodeName);
216 #endif
217     auto surface = CreateSurface(pixelMap_);
218     if (surface == nullptr) {
219         RS_LOGE("RSUiCaptureTaskParallel::Run: surface is nullptr!");
220         return false;
221     }
222     if (!nodeDrawable_) {
223         RS_LOGE("RSUiCaptureTaskParallel::Run: Invalid RSRenderNodeDrawable!");
224         return false;
225     }
226 
227     RSPaintFilterCanvas canvas(surface.get());
228     canvas.Scale(captureConfig_.scaleX, captureConfig_.scaleY);
229     canvas.SetDisableFilterCache(true);
230     canvas.SetUICapture(true);
231     const auto& nodeParams = nodeDrawable_->GetRenderParams();
232     if (nodeParams) {
233         Drawing::Matrix relativeMatrix = Drawing::Matrix();
234         relativeMatrix.Set(Drawing::Matrix::Index::SCALE_X, captureConfig_.scaleX);
235         relativeMatrix.Set(Drawing::Matrix::Index::SCALE_Y, captureConfig_.scaleY);
236         int32_t rectLeft = specifiedAreaRect.GetLeft();
237         int32_t rectTop = specifiedAreaRect.GetTop();
238         const Drawing::scalar x_offset = static_cast<Drawing::scalar>(-1 * rectLeft);
239         const Drawing::scalar y_offset = static_cast<Drawing::scalar>(-1 * rectTop);
240         relativeMatrix.Set(Drawing::Matrix::Index::TRANS_X, x_offset);
241         relativeMatrix.Set(Drawing::Matrix::Index::TRANS_Y, y_offset);
242         RS_LOGD("RSUiCaptureTaskParallel::Run: specifiedAreaRect offsetX is [%{public}f], offsetY is [%{public}f]",
243             x_offset, y_offset);
244         Drawing::Matrix invertMatrix;
245         if (nodeParams->GetMatrix().Invert(invertMatrix)) {
246             relativeMatrix.PreConcat(invertMatrix);
247         }
248         canvas.SetMatrix(relativeMatrix);
249     } else {
250         RS_LOGD("RSUiCaptureTaskParallel::Run: RenderParams is nullptr!");
251     }
252 
253     RSUiFirstProcessStateCheckerHelper stateCheckerHelper(
254         nodeParams->GetFirstLevelNodeId(), nodeParams->GetUifirstRootNodeId());
255     RSUniRenderThread::SetCaptureParam(
256         CaptureParam(true, true, false, captureConfig_.scaleX, captureConfig_.scaleY));
257     nodeDrawable_->OnCapture(canvas);
258     RSUniRenderThread::ResetCaptureParam();
259 
260 #if (defined (RS_ENABLE_GL) || defined (RS_ENABLE_VK)) && (defined RS_ENABLE_EGLIMAGE)
261 #ifdef RS_ENABLE_UNI_RENDER
262     if (RSSystemProperties::GetSnapshotWithDMAEnabled()) {
263         RSUniRenderUtil::OptimizedFlushAndSubmit(surface, grContext, !RSSystemProperties::IsPcType());
264         auto copytask =
265             RSUiCaptureTaskParallel::CreateSurfaceSyncCopyTask(surface, std::move(pixelMap_), nodeId_, callback);
266         if (!copytask) {
267             RS_LOGE("RSUiCaptureTaskParallel::Run: create capture task failed!");
268             return false;
269         }
270         RSBackgroundThread::Instance().PostTask(copytask);
271         return true;
272     } else {
273         std::shared_ptr<Drawing::Image> img(surface.get()->GetImageSnapshot());
274         if (!img) {
275             RS_LOGE("RSUiCaptureTaskParallel::Run: img is nullptr");
276             return false;
277         }
278         if (!CopyDataToPixelMap(img, pixelMap_)) {
279             RS_LOGE("RSUiCaptureTaskParallel::Run: CopyDataToPixelMap failed");
280             return false;
281         }
282     }
283 #endif
284 #endif
285     // To get dump image
286     // execute "param set rosen.dumpsurfacetype.enabled 3 && setenforce 0"
287     RSBaseRenderUtil::WritePixelMapToPng(*pixelMap_);
288     RS_LOGI("RSUiCaptureTaskParallel::Capture DMADisable capture success nodeId:[%{public}" PRIu64
289             "], pixelMap width: %{public}d, height: %{public}d",
290         nodeId_, pixelMap_->GetWidth(), pixelMap_->GetHeight());
291     ProcessUiCaptureCallback(callback, nodeId_, pixelMap_.get());
292     return true;
293 }
294 
CreatePixelMapByRect(const Drawing::Rect & specifiedAreaRect) const295 std::unique_ptr<Media::PixelMap> RSUiCaptureTaskParallel::CreatePixelMapByRect(
296     const Drawing::Rect& specifiedAreaRect) const
297 {
298     float pixmapWidth = specifiedAreaRect.GetWidth();
299     float pixmapHeight = specifiedAreaRect.GetHeight();
300     Media::InitializationOptions opts;
301     opts.size.width = ceil(pixmapWidth * captureConfig_.scaleX);
302     opts.size.height = ceil(pixmapHeight * captureConfig_.scaleY);
303     RS_LOGD("RSUiCaptureTaskParallel::CreatePixelMapByRect:"
304         " origin pixelmap width is [%{public}f], height is [%{public}f],"
305         " created pixelmap width is [%{public}u], height is [%{public}u],"
306         " the scale is scaleX:[%{public}f], scaleY:[%{public}f]",
307         pixmapWidth, pixmapHeight, opts.size.width, opts.size.height,
308         captureConfig_.scaleX, captureConfig_.scaleY);
309     return Media::PixelMap::Create(opts);
310 }
311 
CreatePixelMapByNode(std::shared_ptr<RSRenderNode> node) const312 std::unique_ptr<Media::PixelMap> RSUiCaptureTaskParallel::CreatePixelMapByNode(
313     std::shared_ptr<RSRenderNode> node) const
314 {
315     float pixmapWidth = node->GetRenderProperties().GetBoundsWidth();
316     float pixmapHeight = node->GetRenderProperties().GetBoundsHeight();
317     Media::InitializationOptions opts;
318     opts.size.width = ceil(pixmapWidth * captureConfig_.scaleX);
319     opts.size.height = ceil(pixmapHeight * captureConfig_.scaleY);
320     RS_LOGD("RSUiCaptureTaskParallel::CreatePixelMapByNode: NodeId:[%{public}" PRIu64 "],"
321         " origin pixelmap width is [%{public}f], height is [%{public}f],"
322         " created pixelmap width is [%{public}u], height is [%{public}u],"
323         " the scale is scaleX:[%{public}f], scaleY:[%{public}f]",
324         node->GetId(), pixmapWidth, pixmapHeight, opts.size.width, opts.size.height,
325         captureConfig_.scaleX, captureConfig_.scaleY);
326     return Media::PixelMap::Create(opts);
327 }
328 
CreateSurface(const std::unique_ptr<Media::PixelMap> & pixelmap) const329 std::shared_ptr<Drawing::Surface> RSUiCaptureTaskParallel::CreateSurface(
330     const std::unique_ptr<Media::PixelMap>& pixelmap) const
331 {
332     if (pixelmap == nullptr) {
333         RS_LOGE("RSUiCaptureTaskParallel::CreateSurface: pixelmap == nullptr");
334         return nullptr;
335     }
336     auto address = const_cast<uint32_t*>(pixelmap->GetPixel32(0, 0));
337     if (address == nullptr) {
338         RS_LOGE("RSUiCaptureTaskParallel::CreateSurface: address == nullptr");
339         return nullptr;
340     }
341     Drawing::ImageInfo info = Drawing::ImageInfo{pixelmap->GetWidth(), pixelmap->GetHeight(),
342         Drawing::ColorType::COLORTYPE_RGBA_8888, Drawing::AlphaType::ALPHATYPE_PREMUL};
343 
344 #if (defined RS_ENABLE_GL) && (defined RS_ENABLE_EGLIMAGE)
345     if (RSSystemProperties::GetGpuApiType() == GpuApiType::OPENGL) {
346         auto renderContext = RSUniRenderThread::Instance().GetRenderEngine()->GetRenderContext();
347         if (renderContext == nullptr) {
348             RS_LOGE("RSUiCaptureTaskParallel::CreateSurface: renderContext is nullptr");
349             return nullptr;
350         }
351         renderContext->SetUpGpuContext(nullptr);
352         return Drawing::Surface::MakeRenderTarget(renderContext->GetDrGPUContext(), false, info);
353     }
354 #endif
355 #ifdef RS_ENABLE_VK
356     if (RSSystemProperties::GetGpuApiType() == GpuApiType::VULKAN ||
357         RSSystemProperties::GetGpuApiType() == GpuApiType::DDGR) {
358         return Drawing::Surface::MakeRenderTarget(
359             RSUniRenderThread::Instance().GetRenderEngine()->GetSkContext().get(), false, info);
360     }
361 #endif
362 
363     return Drawing::Surface::MakeRasterDirect(info, address, pixelmap->GetRowBytes());
364 }
365 
366 #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)367 std::function<void()> RSUiCaptureTaskParallel::CreateSurfaceSyncCopyTask(
368     std::shared_ptr<Drawing::Surface> surface, std::unique_ptr<Media::PixelMap> pixelMap,
369     NodeId id, sptr<RSISurfaceCaptureCallback> callback, int32_t rotation, bool useDma)
370 {
371     Drawing::BackendTexture backendTexture = surface->GetBackendTexture();
372     if (!backendTexture.IsValid()) {
373         RS_LOGE("RSUiCaptureTaskParallel: SkiaSurface bind Image failed: BackendTexture is invalid");
374         return {};
375     }
376     auto wrapper = std::make_shared<std::tuple<std::unique_ptr<Media::PixelMap>>>();
377     std::get<0>(*wrapper) = std::move(pixelMap);
378     auto wrapperSf = std::make_shared<std::tuple<std::shared_ptr<Drawing::Surface>>>();
379     std::get<0>(*wrapperSf) = std::move(surface);
380     std::function<void()> copytask = [wrapper, callback, backendTexture, wrapperSf, id, rotation, useDma]() -> void {
381         RS_TRACE_NAME_FMT("copy and send capture useDma:%d", useDma);
382         if (!backendTexture.IsValid()) {
383             RS_LOGE("RSUiCaptureTaskParallel: Surface bind Image failed: BackendTexture is invalid");
384             ProcessUiCaptureCallback(callback, id, nullptr);
385             RSUniRenderUtil::ClearNodeCacheSurface(
386                 std::move(std::get<0>(*wrapperSf)), nullptr, UNI_MAIN_THREAD_INDEX, 0);
387             return;
388         }
389         auto pixelmap = std::move(std::get<0>(*wrapper));
390         if (pixelmap == nullptr) {
391             RS_LOGE("RSUiCaptureTaskParallel: pixelmap == nullptr");
392             ProcessUiCaptureCallback(callback, id, nullptr);
393             RSUniRenderUtil::ClearNodeCacheSurface(
394                 std::move(std::get<0>(*wrapperSf)), nullptr, UNI_MAIN_THREAD_INDEX, 0);
395             return;
396         }
397 
398         Drawing::ImageInfo info = Drawing::ImageInfo{ pixelmap->GetWidth(), pixelmap->GetHeight(),
399             Drawing::COLORTYPE_RGBA_8888, Drawing::ALPHATYPE_PREMUL };
400         Drawing::TextureOrigin textureOrigin = Drawing::TextureOrigin::BOTTOM_LEFT;
401         Drawing::BitmapFormat bitmapFormat =
402             Drawing::BitmapFormat{ Drawing::COLORTYPE_RGBA_8888, Drawing::ALPHATYPE_PREMUL };
403         std::shared_ptr<Drawing::Surface> surface;
404         auto grContext = RSBackgroundThread::Instance().GetShareGPUContext();
405         if (!grContext) {
406             RS_LOGE("RSUiCaptureTaskParallel: SharedGPUContext get failed");
407             ProcessUiCaptureCallback(callback, id, nullptr);
408             return;
409         }
410 #if defined(ROSEN_OHOS) && defined(RS_ENABLE_VK)
411         DmaMem dmaMem;
412         if (useDma && RSMainThread::Instance()->GetDeviceType() == DeviceType::PHONE &&
413             (RSSystemProperties::GetGpuApiType() == GpuApiType::VULKAN ||
414             RSSystemProperties::GetGpuApiType() == GpuApiType::DDGR)) {
415             sptr<SurfaceBuffer> surfaceBuffer = dmaMem.DmaMemAlloc(info, pixelmap);
416             surface = dmaMem.GetSurfaceFromSurfaceBuffer(surfaceBuffer, grContext);
417             if (surface == nullptr) {
418                 RS_LOGE("RSUiCaptureTaskParallel: GetSurfaceFromSurfaceBuffer fail.");
419                 ProcessUiCaptureCallback(callback, id, nullptr);
420                 RSUniRenderUtil::ClearNodeCacheSurface(
421                     std::move(std::get<0>(*wrapperSf)), nullptr, UNI_MAIN_THREAD_INDEX, 0);
422                 return;
423             }
424             auto tmpImg = std::make_shared<Drawing::Image>();
425             DrawCapturedImg(*tmpImg, *surface, backendTexture, textureOrigin, bitmapFormat);
426         } else {
427 #else
428         {
429 #endif
430             auto tmpImg = std::make_shared<Drawing::Image>();
431             tmpImg->BuildFromTexture(*grContext, backendTexture.GetTextureInfo(),
432                 textureOrigin, bitmapFormat, nullptr);
433             if (!CopyDataToPixelMap(tmpImg, pixelmap)) {
434                 RS_LOGE("RSUiCaptureTaskParallel: CopyDataToPixelMap failed");
435                 ProcessUiCaptureCallback(callback, id, nullptr);
436                 RSUniRenderUtil::ClearNodeCacheSurface(
437                     std::move(std::get<0>(*wrapperSf)), nullptr, UNI_MAIN_THREAD_INDEX, 0);
438                 return;
439             }
440         }
441         if (rotation) {
442             pixelmap->rotate(rotation);
443         }
444         // To get dump image
445         // execute "param set rosen.dumpsurfacetype.enabled 3 && setenforce 0"
446         RSBaseRenderUtil::WritePixelMapToPng(*pixelmap);
447         RS_LOGI("RSUiCaptureTaskParallel::Capture capture success nodeId:[%{public}" PRIu64
448                 "], pixelMap width: %{public}d, height: %{public}d",
449             id, pixelmap->GetWidth(), pixelmap->GetHeight());
450         ProcessUiCaptureCallback(callback, id, pixelmap.get());
451         RSBackgroundThread::Instance().CleanGrResource();
452         RSUniRenderUtil::ClearNodeCacheSurface(
453             std::move(std::get<0>(*wrapperSf)), nullptr, UNI_MAIN_THREAD_INDEX, 0);
454     };
455     return copytask;
456 }
457 #endif
458 
459 void RSUiCaptureTaskParallel::ProcessUiCaptureCallback(
460     sptr<RSISurfaceCaptureCallback> callback, NodeId id, Media::PixelMap* pixelmap)
461 {
462     callback->OnSurfaceCapture(id, pixelmap);
463     RSUiCaptureTaskParallel::captureCount_--;
464     RSMainThread::Instance()->RequestNextVSync();
465 }
466 } // namespace Rosen
467 } // namespace OHOS
468