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