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