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