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_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 "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_uifirst_manager.h"
36 #include "pipeline/rs_uni_render_judgement.h"
37 #include "pipeline/rs_uni_render_util.h"
38 #include "platform/common/rs_log.h"
39 #include "platform/drawing/rs_surface.h"
40 #include "render/rs_drawing_filter.h"
41 #include "render/rs_skia_filter.h"
42 #include "screen_manager/rs_screen_manager.h"
43 #include "screen_manager/rs_screen_mode_info.h"
44
45 namespace OHOS {
46 namespace Rosen {
47 namespace {
DrawCapturedImg(Drawing::Image & image,Drawing::Surface & surface,const Drawing::BackendTexture & backendTexture,Drawing::TextureOrigin & textureOrigin,Drawing::BitmapFormat & bitmapFormat)48 inline void DrawCapturedImg(Drawing::Image& image,
49 Drawing::Surface& surface, const Drawing::BackendTexture& backendTexture,
50 Drawing::TextureOrigin& textureOrigin, Drawing::BitmapFormat& bitmapFormat)
51 {
52 RSPaintFilterCanvas canvas(&surface);
53 auto gpuContext = canvas.GetGPUContext();
54 if (gpuContext == nullptr) {
55 RS_LOGE("DrawCapturedImg failed: gpuContext is nullptr");
56 return;
57 }
58 image.BuildFromTexture(*gpuContext, backendTexture.GetTextureInfo(),
59 textureOrigin, bitmapFormat, nullptr);
60 canvas.DrawImage(image, 0.f, 0.f, Drawing::SamplingOptions());
61 surface.FlushAndSubmit(true);
62 }
63 }
64
CheckModifiers(NodeId id,bool useCurWindow)65 void RSSurfaceCaptureTaskParallel::CheckModifiers(NodeId id, bool useCurWindow)
66 {
67 RS_TRACE_NAME("RSSurfaceCaptureTaskParallel::CheckModifiers");
68 bool needSync = RSMainThread::Instance()->IsOcclusionNodesNeedSync(id, useCurWindow) ||
69 RSMainThread::Instance()->IsHardwareEnabledNodesNeedSync();
70 if (!needSync) {
71 return;
72 }
73 std::function<void()> syncTask = []() -> void {
74 RS_TRACE_NAME("RSSurfaceCaptureTaskParallel::SyncModifiers");
75 auto& pendingSyncNodes = RSMainThread::Instance()->GetContext().pendingSyncNodes_;
76 for (auto& [id, weakPtr] : pendingSyncNodes) {
77 auto node = weakPtr.lock();
78 if (node == nullptr) {
79 continue;
80 }
81 if (!RSUifirstManager::Instance().CollectSkipSyncNode(node)) {
82 node->Sync();
83 } else {
84 node->SkipSync();
85 }
86 }
87 pendingSyncNodes.clear();
88 RSUifirstManager::Instance().UifirstCurStateClear();
89 };
90 RSUniRenderThread::Instance().PostSyncTask(syncTask);
91 }
92
Capture(NodeId id,sptr<RSISurfaceCaptureCallback> callback,const RSSurfaceCaptureConfig & captureConfig,bool isSystemCalling)93 void RSSurfaceCaptureTaskParallel::Capture(NodeId id,
94 sptr<RSISurfaceCaptureCallback> callback, const RSSurfaceCaptureConfig& captureConfig, bool isSystemCalling)
95 {
96 if (callback == nullptr) {
97 RS_LOGE("RSSurfaceCaptureTaskParallel::Capture nodeId:[%{public}" PRIu64 "], callback is nullptr", id);
98 return;
99 }
100 std::shared_ptr<RSSurfaceCaptureTaskParallel> captureHandle =
101 std::make_shared<RSSurfaceCaptureTaskParallel>(id, captureConfig);
102 if (captureHandle == nullptr) {
103 RS_LOGD("RSSurfaceCaptureTaskParallel::Capture captureHandle is nullptr!");
104 callback->OnSurfaceCapture(id, nullptr);
105 return;
106 }
107 if (!captureHandle->CreateResources()) {
108 callback->OnSurfaceCapture(id, nullptr);
109 return;
110 }
111
112 std::function<void()> captureTask = [captureHandle, id, callback, isSystemCalling]() -> void {
113 RS_TRACE_NAME("RSSurfaceCaptureTaskParallel::TakeSurfaceCapture");
114 if (!captureHandle->Run(callback, isSystemCalling)) {
115 callback->OnSurfaceCapture(id, nullptr);
116 }
117 };
118 RSUniRenderThread::Instance().PostSyncTask(captureTask);
119 }
120
CreateResources()121 bool RSSurfaceCaptureTaskParallel::CreateResources()
122 {
123 RS_LOGD("RSSurfaceCaptureTaskParallel capture nodeId:[%{public}" PRIu64 "]", nodeId_);
124 if (ROSEN_EQ(captureConfig_.scaleX, 0.f) || ROSEN_EQ(captureConfig_.scaleY, 0.f) ||
125 captureConfig_.scaleX < 0.f || captureConfig_.scaleY < 0.f ||
126 captureConfig_.scaleX > 1.f || captureConfig_.scaleY > 1.f) {
127 RS_LOGE("RSSurfaceCaptureTaskParallel::CreateResources: SurfaceCapture scale is invalid.");
128 return false;
129 }
130 auto node = RSMainThread::Instance()->GetContext().GetNodeMap().GetRenderNode(nodeId_);
131 if (node == nullptr) {
132 RS_LOGE("RSSurfaceCaptureTaskParallel::CreateResources: Invalid nodeId:[%{public}" PRIu64 "]",
133 nodeId_);
134 return false;
135 }
136
137 if (auto surfaceNode = node->ReinterpretCastTo<RSSurfaceRenderNode>()) {
138 auto curNode = surfaceNode;
139 if (!captureConfig_.useCurWindow) {
140 auto parentNode = RSBaseRenderNode::ReinterpretCast<RSSurfaceRenderNode>(surfaceNode->GetParent().lock());
141 if (parentNode && parentNode->IsLeashWindow() && parentNode->ShouldPaint()) {
142 curNode = parentNode;
143 }
144 }
145 if (!curNode->ShouldPaint()) {
146 RS_LOGE("RSSurfaceCaptureTaskParallel::CreateResources: Node should not paint!");
147 return false;
148 }
149
150 surfaceNodeDrawable_ = std::static_pointer_cast<DrawableV2::RSRenderNodeDrawable>(
151 DrawableV2::RSRenderNodeDrawableAdapter::OnGenerate(curNode));
152 pixelMap_ = CreatePixelMapBySurfaceNode(curNode);
153 } else if (auto displayNode = node->ReinterpretCastTo<RSDisplayRenderNode>()) {
154 displayNodeDrawable_ = std::static_pointer_cast<DrawableV2::RSRenderNodeDrawable>(
155 DrawableV2::RSRenderNodeDrawableAdapter::OnGenerate(displayNode));
156 pixelMap_ = CreatePixelMapByDisplayNode(displayNode);
157 } else {
158 RS_LOGE("RSSurfaceCaptureTaskParallel::CreateResources: Invalid RSRenderNodeType!");
159 return false;
160 }
161 if (pixelMap_ == nullptr) {
162 RS_LOGE("RSSurfaceCaptureTaskParallel::CreateResources: pixelMap_ is nullptr!");
163 return false;
164 }
165 return true;
166 }
167
Run(sptr<RSISurfaceCaptureCallback> callback,bool isSystemCalling)168 bool RSSurfaceCaptureTaskParallel::Run(sptr<RSISurfaceCaptureCallback> callback, bool isSystemCalling)
169 {
170 #if defined(RS_ENABLE_GL) || defined(RS_ENABLE_VK)
171 SetupGpuContext();
172 std::string nodeName("RSSurfaceCaptureTaskParallel");
173 RSTagTracker tagTracker(gpuContext_.get(), nodeId_, RSTagTracker::TAGTYPE::TAG_CAPTURE, nodeName);
174 #endif
175 auto surface = CreateSurface(pixelMap_);
176 if (surface == nullptr) {
177 RS_LOGE("RSSurfaceCaptureTaskParallel::Run: surface is nullptr!");
178 return false;
179 }
180
181 RSPaintFilterCanvas canvas(surface.get());
182 canvas.Scale(captureConfig_.scaleX, captureConfig_.scaleY);
183 canvas.SetDisableFilterCache(true);
184 RSSurfaceRenderParams* curNodeParams = nullptr;
185 // Currently, capture do not support HDR display
186 canvas.SetCapture(true);
187 if (surfaceNodeDrawable_) {
188 curNodeParams = static_cast<RSSurfaceRenderParams*>(surfaceNodeDrawable_->GetRenderParams().get());
189 // make sure the previous uifirst task is completed.
190 if (!RSUiFirstProcessStateCheckerHelper::CheckMatchAndWaitNotify(*curNodeParams, false)) {
191 return false;
192 }
193 RSUiFirstProcessStateCheckerHelper stateCheckerHelper(
194 curNodeParams->GetFirstLevelNodeId(), curNodeParams->GetUifirstRootNodeId());
195 RSUniRenderThread::SetCaptureParam(
196 CaptureParam(true, true, false, captureConfig_.scaleX, captureConfig_.scaleY, true, isSystemCalling));
197 surfaceNodeDrawable_->OnCapture(canvas);
198 } else if (displayNodeDrawable_) {
199 RSUniRenderThread::SetCaptureParam(
200 CaptureParam(true, false, false, captureConfig_.scaleX, captureConfig_.scaleY));
201 displayNodeDrawable_->OnCapture(canvas);
202 } else {
203 RS_LOGE("RSSurfaceCaptureTaskParallel::Run: Invalid RSRenderNodeDrawable!");
204 return false;
205 }
206 RSUniRenderThread::ResetCaptureParam();
207
208 #if (defined (RS_ENABLE_GL) || defined (RS_ENABLE_VK)) && (defined RS_ENABLE_EGLIMAGE)
209 #ifdef RS_ENABLE_UNI_RENDER
210 RSUniRenderUtil::OptimizedFlushAndSubmit(surface, gpuContext_.get(), !RSSystemProperties::IsPcType());
211 if (curNodeParams && curNodeParams->IsNodeToBeCaptured()) {
212 RSUifirstManager::Instance().AddCapturedNodes(curNodeParams->GetId());
213 }
214 if (RSSystemProperties::GetSnapshotWithDMAEnabled()) {
215 auto copytask = CreateSurfaceSyncCopyTask(surface, std::move(pixelMap_),
216 nodeId_, callback, finalRotationAngle_, captureConfig_.useDma);
217 if (!copytask) {
218 RS_LOGE("RSSurfaceCaptureTaskParallel::Run: create capture task failed!");
219 return false;
220 }
221 RSBackgroundThread::Instance().PostTask(copytask);
222 return true;
223 } else {
224 std::shared_ptr<Drawing::Image> img(surface.get()->GetImageSnapshot());
225 if (!img) {
226 RS_LOGE("RSSurfaceCaptureTaskParallel::Run: img is nullptr");
227 return false;
228 }
229 if (!CopyDataToPixelMap(img, pixelMap_)) {
230 RS_LOGE("RSSurfaceCaptureTaskParallel::Run: CopyDataToPixelMap failed");
231 return false;
232 }
233 }
234 #endif
235 #endif
236 if (finalRotationAngle_) {
237 pixelMap_->rotate(finalRotationAngle_);
238 }
239 // To get dump image
240 // execute "param set rosen.dumpsurfacetype.enabled 3 && setenforce 0"
241 RSBaseRenderUtil::WritePixelMapToPng(*pixelMap_);
242 callback->OnSurfaceCapture(nodeId_, pixelMap_.get());
243 return true;
244 }
245
CreatePixelMapBySurfaceNode(std::shared_ptr<RSSurfaceRenderNode> node)246 std::unique_ptr<Media::PixelMap> RSSurfaceCaptureTaskParallel::CreatePixelMapBySurfaceNode(
247 std::shared_ptr<RSSurfaceRenderNode> node)
248 {
249 if (node == nullptr) {
250 RS_LOGE("RSSurfaceCaptureTaskParallel::CreatePixelMapBySurfaceNode: node == nullptr");
251 return nullptr;
252 }
253 int pixmapWidth = node->GetRenderProperties().GetBoundsWidth();
254 int pixmapHeight = node->GetRenderProperties().GetBoundsHeight();
255
256 Media::InitializationOptions opts;
257 opts.size.width = ceil(pixmapWidth * captureConfig_.scaleX);
258 opts.size.height = ceil(pixmapHeight * captureConfig_.scaleY);
259 RS_LOGD("RSSurfaceCaptureTaskParallel::CreatePixelMapBySurfaceNode: NodeId:[%{public}" PRIu64 "],"
260 " origin pixelmap size: [%{public}u, %{public}u],"
261 " created pixelmap size: [%{public}u, %{public}u],"
262 " scale: [%{public}f, %{public}f],"
263 " useDma: [%{public}d], useCurWindow: [%{public}d]",
264 node->GetId(), pixmapWidth, pixmapHeight, opts.size.width, opts.size.height,
265 captureConfig_.scaleX, captureConfig_.scaleY, captureConfig_.useDma, captureConfig_.useCurWindow);
266 return Media::PixelMap::Create(opts);
267 }
268
CreatePixelMapByDisplayNode(std::shared_ptr<RSDisplayRenderNode> node)269 std::unique_ptr<Media::PixelMap> RSSurfaceCaptureTaskParallel::CreatePixelMapByDisplayNode(
270 std::shared_ptr<RSDisplayRenderNode> node)
271 {
272 if (node == nullptr) {
273 RS_LOGE("RSSurfaceCaptureTaskParallel::CreatePixelMapByDisplayNode: node is nullptr");
274 return nullptr;
275 }
276 uint64_t screenId = node->GetScreenId();
277 sptr<RSScreenManager> screenManager = CreateOrGetScreenManager();
278 if (!screenManager) {
279 RS_LOGE("RSSurfaceCaptureTaskParallel::CreatePixelMapByDisplayNode: screenManager is nullptr!");
280 return nullptr;
281 }
282 auto screenInfo = screenManager->QueryScreenInfo(screenId);
283 screenCorrection_ = screenManager->GetScreenCorrection(screenId);
284 screenRotation_ = node->GetScreenRotation();
285 finalRotationAngle_ = CalPixelMapRotation();
286 uint32_t pixmapWidth = screenInfo.width;
287 uint32_t pixmapHeight = screenInfo.height;
288
289 Media::InitializationOptions opts;
290 opts.size.width = ceil(pixmapWidth * captureConfig_.scaleX);
291 opts.size.height = ceil(pixmapHeight * captureConfig_.scaleY);
292 RS_LOGI("RSSurfaceCaptureTaskParallel::CreatePixelMapByDisplayNode: NodeId:[%{public}" PRIu64 "],"
293 " origin pixelmap size: [%{public}u, %{public}u],"
294 " created pixelmap size: [%{public}u, %{public}u],"
295 " scale: [%{public}f, %{public}f],"
296 " useDma: [%{public}d]",
297 node->GetId(), pixmapWidth, pixmapHeight, opts.size.width, opts.size.height,
298 captureConfig_.scaleX, captureConfig_.scaleY, captureConfig_.useDma);
299 return Media::PixelMap::Create(opts);
300 }
301
CreateSurface(const std::unique_ptr<Media::PixelMap> & pixelmap)302 std::shared_ptr<Drawing::Surface> RSSurfaceCaptureTaskParallel::CreateSurface(
303 const std::unique_ptr<Media::PixelMap>& pixelmap)
304 {
305 if (pixelmap == nullptr) {
306 RS_LOGE("RSSurfaceCaptureTaskParallel::CreateSurface: pixelmap == nullptr");
307 return nullptr;
308 }
309 auto address = const_cast<uint32_t*>(pixelmap->GetPixel32(0, 0));
310 if (address == nullptr) {
311 RS_LOGE("RSSurfaceCaptureTaskParallel::CreateSurface: address == nullptr");
312 return nullptr;
313 }
314 Drawing::ImageInfo info = Drawing::ImageInfo{pixelmap->GetWidth(), pixelmap->GetHeight(),
315 Drawing::ColorType::COLORTYPE_RGBA_8888, Drawing::AlphaType::ALPHATYPE_PREMUL};
316
317 #if (defined RS_ENABLE_GL) && (defined RS_ENABLE_EGLIMAGE)
318 if (RSSystemProperties::GetGpuApiType() == GpuApiType::OPENGL) {
319 auto renderEngine = RSUniRenderThread::Instance().GetRenderEngine();
320 if (renderEngine == nullptr) {
321 RS_LOGE("RSSurfaceCaptureTaskParallel::CreateSurface: renderEngine is nullptr");
322 return nullptr;
323 }
324 auto renderContext = renderEngine->GetRenderContext();
325 if (renderContext == nullptr) {
326 RS_LOGE("RSSurfaceCaptureTaskParallel::CreateSurface: renderContext is nullptr");
327 return nullptr;
328 }
329 renderContext->SetUpGpuContext(nullptr);
330 return Drawing::Surface::MakeRenderTarget(renderContext->GetDrGPUContext(), false, info);
331 }
332 #endif
333 #ifdef RS_ENABLE_VK
334 if (RSSystemProperties::GetGpuApiType() == GpuApiType::VULKAN ||
335 RSSystemProperties::GetGpuApiType() == GpuApiType::DDGR) {
336 return Drawing::Surface::MakeRenderTarget(gpuContext_.get(), false, info);
337 }
338 #endif
339
340 return Drawing::Surface::MakeRasterDirect(info, address, pixelmap->GetRowBytes());
341 }
342
SetupGpuContext()343 void RSSurfaceCaptureTaskParallel::SetupGpuContext()
344 {
345 auto renderEngine = RSUniRenderThread::Instance().GetRenderEngine();
346 if (renderEngine == nullptr) {
347 RS_LOGE("RSSurfaceCaptureTaskParallel::SetupGpuContext: renderEngine is nullptr");
348 return;
349 }
350 auto renderContext = renderEngine->GetRenderContext();
351 gpuContext_ = renderContext != nullptr ? renderContext->GetSharedDrGPUContext() : nullptr;
352 if (gpuContext_ == nullptr) {
353 RS_LOGW("RSSurfaceCaptureTaskParallel::SetupGpuContext gpuContext_ is nullptr");
354 }
355 }
356
CalPixelMapRotation()357 int32_t RSSurfaceCaptureTaskParallel::CalPixelMapRotation()
358 {
359 auto screenRotation = ScreenRotationMapping(screenRotation_);
360 auto screenCorrection = ScreenRotationMapping(screenCorrection_);
361 int32_t rotation = screenRotation - screenCorrection;
362 RS_LOGI("RSSurfaceCaptureTaskParallel::CalPixelMapRotation: screenRotation:%{public}d"
363 " screenCorrection:%{public}d", screenRotation, screenCorrection);
364 return rotation;
365 }
366
367 #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)368 std::function<void()> RSSurfaceCaptureTaskParallel::CreateSurfaceSyncCopyTask(
369 std::shared_ptr<Drawing::Surface> surface, std::unique_ptr<Media::PixelMap> pixelMap,
370 NodeId id, sptr<RSISurfaceCaptureCallback> callback, int32_t rotation, bool useDma)
371 {
372 if (surface == nullptr) {
373 RS_LOGE("RSSurfaceCaptureTaskParallel: nodeId:[%{public}" PRIu64 "], surface is nullptr", id);
374 return {};
375 }
376 Drawing::BackendTexture backendTexture = surface->GetBackendTexture();
377 if (!backendTexture.IsValid()) {
378 RS_LOGE("RSSurfaceCaptureTaskParallel: SkiaSurface bind Image failed: BackendTexture is invalid");
379 return {};
380 }
381 auto wrapper = std::make_shared<std::tuple<std::unique_ptr<Media::PixelMap>>>();
382 std::get<0>(*wrapper) = std::move(pixelMap);
383 auto wrapperSf = std::make_shared<std::tuple<std::shared_ptr<Drawing::Surface>>>();
384 std::get<0>(*wrapperSf) = std::move(surface);
385 std::function<void()> copytask = [wrapper, callback, backendTexture, wrapperSf, id, rotation, useDma]() -> void {
386 RS_TRACE_NAME_FMT("copy and send capture useDma:%d", useDma);
387 if (callback == nullptr) {
388 RS_LOGE("RSSurfaceCaptureTaskParallel: nodeId:[%{public}" PRIu64 "], callback is nullptr", id);
389 return;
390 }
391 if (!backendTexture.IsValid()) {
392 RS_LOGE("RSSurfaceCaptureTaskParallel: Surface bind Image failed: BackendTexture is invalid");
393 callback->OnSurfaceCapture(id, nullptr);
394 RSUniRenderUtil::ClearNodeCacheSurface(
395 std::move(std::get<0>(*wrapperSf)), nullptr, UNI_MAIN_THREAD_INDEX, 0);
396 return;
397 }
398 auto pixelmap = std::move(std::get<0>(*wrapper));
399 if (pixelmap == nullptr) {
400 RS_LOGE("RSSurfaceCaptureTaskParallel: pixelmap == nullptr");
401 callback->OnSurfaceCapture(id, nullptr);
402 RSUniRenderUtil::ClearNodeCacheSurface(
403 std::move(std::get<0>(*wrapperSf)), nullptr, UNI_MAIN_THREAD_INDEX, 0);
404 return;
405 }
406
407 Drawing::ImageInfo info = Drawing::ImageInfo{ pixelmap->GetWidth(), pixelmap->GetHeight(),
408 Drawing::COLORTYPE_RGBA_8888, Drawing::ALPHATYPE_PREMUL };
409 Drawing::TextureOrigin textureOrigin = Drawing::TextureOrigin::BOTTOM_LEFT;
410 Drawing::BitmapFormat bitmapFormat =
411 Drawing::BitmapFormat{ Drawing::COLORTYPE_RGBA_8888, Drawing::ALPHATYPE_PREMUL };
412 std::shared_ptr<Drawing::Surface> surface;
413 auto grContext = RSBackgroundThread::Instance().GetShareGPUContext();
414 #if defined(ROSEN_OHOS) && defined(RS_ENABLE_VK)
415 DmaMem dmaMem;
416 if (useDma && RSMainThread::Instance()->GetDeviceType() == DeviceType::PHONE &&
417 (RSSystemProperties::GetGpuApiType() == GpuApiType::VULKAN ||
418 RSSystemProperties::GetGpuApiType() == GpuApiType::DDGR)) {
419 sptr<SurfaceBuffer> surfaceBuffer = dmaMem.DmaMemAlloc(info, pixelmap);
420 surface = dmaMem.GetSurfaceFromSurfaceBuffer(surfaceBuffer, grContext);
421 if (surface == nullptr) {
422 RS_LOGE("RSSurfaceCaptureTaskParallel: GetSurfaceFromSurfaceBuffer fail.");
423 callback->OnSurfaceCapture(id, nullptr);
424 RSUniRenderUtil::ClearNodeCacheSurface(
425 std::move(std::get<0>(*wrapperSf)), nullptr, UNI_MAIN_THREAD_INDEX, 0);
426 return;
427 }
428 auto tmpImg = std::make_shared<Drawing::Image>();
429 DrawCapturedImg(*tmpImg, *surface, backendTexture, textureOrigin, bitmapFormat);
430 } else {
431 #else
432 {
433 #endif
434 auto tmpImg = std::make_shared<Drawing::Image>();
435 tmpImg->BuildFromTexture(*grContext, backendTexture.GetTextureInfo(),
436 textureOrigin, bitmapFormat, nullptr);
437 if (!CopyDataToPixelMap(tmpImg, pixelmap)) {
438 RS_LOGE("RSSurfaceCaptureTaskParallel: CopyDataToPixelMap failed");
439 callback->OnSurfaceCapture(id, nullptr);
440 RSUniRenderUtil::ClearNodeCacheSurface(
441 std::move(std::get<0>(*wrapperSf)), nullptr, UNI_MAIN_THREAD_INDEX, 0);
442 return;
443 }
444 }
445 if (rotation) {
446 pixelmap->rotate(rotation);
447 }
448 // To get dump image
449 // execute "param set rosen.dumpsurfacetype.enabled 3 && setenforce 0"
450 RSBaseRenderUtil::WritePixelMapToPng(*pixelmap);
451 callback->OnSurfaceCapture(id, pixelmap.get());
452 RSBackgroundThread::Instance().CleanGrResource();
453 RSUniRenderUtil::ClearNodeCacheSurface(
454 std::move(std::get<0>(*wrapperSf)), nullptr, UNI_MAIN_THREAD_INDEX, 0);
455 };
456 return copytask;
457 }
458 #endif
459
460 #if defined(ROSEN_OHOS) && defined(RS_ENABLE_VK)
461 DmaMem::~DmaMem()
462 {
463 ReleaseDmaMemory();
464 }
465
466 void DmaMem::ReleaseDmaMemory()
467 {
468 if (nativeWindowBuffer_ != nullptr) {
469 DestroyNativeWindowBuffer(nativeWindowBuffer_);
470 nativeWindowBuffer_ = nullptr;
471 }
472 }
473
474 sptr<SurfaceBuffer> DmaMem::DmaMemAlloc(Drawing::ImageInfo &dstInfo, const std::unique_ptr<Media::PixelMap>& pixelmap)
475 {
476 #if defined(_WIN32) || defined(_APPLE) || defined(A_PLATFORM) || defined(IOS_PLATFORM)
477 RS_LOGE("Unsupport dma mem alloc");
478 return nullptr;
479 #else
480 if (pixelmap == nullptr) {
481 RS_LOGE("DmaMem::DmaMemAlloc: pixelmap is nullptr");
482 return nullptr;
483 }
484 sptr<SurfaceBuffer> surfaceBuffer = SurfaceBuffer::Create();
485 if (!surfaceBuffer) {
486 RS_LOGE("DmaMem::DmaMemAlloc: surfaceBuffer create failed");
487 return nullptr;
488 }
489 BufferRequestConfig requestConfig = {
490 .width = dstInfo.GetWidth(),
491 .height = dstInfo.GetHeight(),
492 .strideAlignment = 0x8, // set 0x8 as default value to alloc SurfaceBufferImpl
493 .format = GRAPHIC_PIXEL_FMT_RGBA_8888, // PixelFormat
494 .usage = BUFFER_USAGE_CPU_READ | BUFFER_USAGE_HW_RENDER | BUFFER_USAGE_HW_TEXTURE | BUFFER_USAGE_MEM_DMA,
495 .timeout = 0,
496 .colorGamut = GraphicColorGamut::GRAPHIC_COLOR_GAMUT_SRGB,
497 .transform = GraphicTransformType::GRAPHIC_ROTATE_NONE,
498 };
499 GSError ret = surfaceBuffer->Alloc(requestConfig);
500 if (ret != GSERROR_OK) {
501 RS_LOGE("DmaMem::DmaMemAlloc: surfaceBuffer alloc failed, %{public}s", GSErrorStr(ret).c_str());
502 return nullptr;
503 }
504 void* nativeBuffer = surfaceBuffer.GetRefPtr();
505 OHOS::RefBase *ref = reinterpret_cast<OHOS::RefBase *>(nativeBuffer);
506 ref->IncStrongRef(ref);
507 int32_t bufferSize = pixelmap->GetByteCount();
508 pixelmap->SetPixelsAddr(surfaceBuffer->GetVirAddr(), nativeBuffer, bufferSize,
509 Media::AllocatorType::DMA_ALLOC, nullptr);
510 return surfaceBuffer;
511 #endif
512 }
513
514 static inline void DeleteVkImage(void *context)
515 {
516 NativeBufferUtils::VulkanCleanupHelper *cleanupHelper =
517 static_cast<NativeBufferUtils::VulkanCleanupHelper *> (context);
518 if (cleanupHelper != nullptr) {
519 cleanupHelper->UnRef();
520 }
521 }
522
523 std::shared_ptr<Drawing::Surface> DmaMem::GetSurfaceFromSurfaceBuffer(
524 sptr<SurfaceBuffer> surfaceBuffer, std::shared_ptr<Drawing::GPUContext> gpuContext)
525 {
526 if (surfaceBuffer == nullptr || gpuContext == nullptr) {
527 RS_LOGE("GetSurfaceFromSurfaceBuffer surfaceBuffer or gpuContext is nullptr");
528 return nullptr;
529 }
530 if (nativeWindowBuffer_ == nullptr) {
531 nativeWindowBuffer_ = CreateNativeWindowBufferFromSurfaceBuffer(&surfaceBuffer);
532 if (!nativeWindowBuffer_) {
533 RS_LOGE("DmaMem::GetSurfaceFromSurfaceBuffer: nativeWindowBuffer_ is nullptr");
534 return nullptr;
535 }
536 }
537
538 Drawing::BackendTexture backendTextureTmp =
539 NativeBufferUtils::MakeBackendTextureFromNativeBuffer(nativeWindowBuffer_,
540 surfaceBuffer->GetWidth(), surfaceBuffer->GetHeight());
541 if (!backendTextureTmp.IsValid()) {
542 return nullptr;
543 }
544
545 auto vkTextureInfo = backendTextureTmp.GetTextureInfo().GetVKTextureInfo();
546 if (vkTextureInfo == nullptr) {
547 return nullptr;
548 }
549 vkTextureInfo->imageUsageFlags = vkTextureInfo->imageUsageFlags | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
550 auto cleanUpHelper = new NativeBufferUtils::VulkanCleanupHelper(RsVulkanContext::GetSingleton(),
551 vkTextureInfo->vkImage, vkTextureInfo->vkAlloc.memory);
552 if (cleanUpHelper == nullptr) {
553 return nullptr;
554 }
555 // attention: cleanUpHelper will be delete by NativeBufferUtils::DeleteVkImage, don't delete again
556 auto drawingSurface = Drawing::Surface::MakeFromBackendTexture(
557 gpuContext.get(),
558 backendTextureTmp.GetTextureInfo(),
559 Drawing::TextureOrigin::TOP_LEFT,
560 1, Drawing::ColorType::COLORTYPE_RGBA_8888, nullptr,
561 NativeBufferUtils::DeleteVkImage, cleanUpHelper);
562 return drawingSurface;
563 }
564 #endif
565 } // namespace Rosen
566 } // namespace OHOS
567