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