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