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