1 /*
2 * Copyright (c) 2021-2023 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "feature/capture/rs_surface_capture_task.h"
17
18 #include <memory>
19 #include <sys/mman.h>
20
21 #include "rs_trace.h"
22
23 #include "common/rs_background_thread.h"
24 #include "common/rs_obj_abs_geometry.h"
25 #include "draw/color.h"
26 #include "draw/surface.h"
27 #include "drawable/rs_screen_render_node_drawable.h"
28 #include "memory/rs_tag_tracker.h"
29 #include "pipeline/render_thread/rs_base_render_engine.h"
30 #include "pipeline/render_thread/rs_composer_adapter.h"
31 #include "pipeline/render_thread/rs_uni_render_util.h"
32 #include "pipeline/rs_base_render_node.h"
33 #include "pipeline/rs_canvas_drawing_render_node.h"
34 #include "pipeline/render_thread/rs_divided_render_util.h"
35 #include "pipeline/rs_effect_render_node.h"
36 #include "pipeline/main_thread/rs_main_thread.h"
37 #include "pipeline/main_thread/rs_render_service_connection.h"
38 #include "pipeline/rs_logical_display_render_node.h"
39 #include "pipeline/rs_root_render_node.h"
40 #include "pipeline/rs_surface_render_node.h"
41 #include "pipeline/rs_uni_render_judgement.h"
42 #include "platform/common/rs_log.h"
43 #include "platform/drawing/rs_surface.h"
44 #include "render/rs_drawing_filter.h"
45 #include "render/rs_skia_filter.h"
46 #include "screen_manager/rs_screen_manager.h"
47 #include "screen_manager/rs_screen_mode_info.h"
48 namespace OHOS {
49 namespace Rosen {
Run(sptr<RSISurfaceCaptureCallback> callback)50 bool RSSurfaceCaptureTask::Run(sptr<RSISurfaceCaptureCallback> callback)
51 {
52 if (ROSEN_EQ(captureConfig_.scaleX, 0.f) || ROSEN_EQ(captureConfig_.scaleY, 0.f) ||
53 captureConfig_.scaleX < 0.f || captureConfig_.scaleY < 0.f) {
54 RS_LOGE("RSSurfaceCaptureTask::Run: SurfaceCapture scale is invalid.");
55 return false;
56 }
57 auto node = RSMainThread::Instance()->GetContext().GetNodeMap().GetRenderNode(nodeId_);
58 if (node == nullptr) {
59 RS_LOGE("RSSurfaceCaptureTask::Run: node is nullptr");
60 return false;
61 }
62 std::unique_ptr<Media::PixelMap> pixelmap;
63 visitor_ = std::make_shared<RSSurfaceCaptureVisitor>(captureConfig_, RSUniRenderJudgement::IsUniRender());
64 std::string nodeName("RSSurfaceCaptureTask");
65 std::shared_ptr<Drawing::ColorSpace> colorSpace = nullptr;
66 if (auto surfaceNode = node->ReinterpretCastTo<RSSurfaceRenderNode>()) {
67 pixelmap = CreatePixelMapBySurfaceNode(surfaceNode, visitor_->IsUniRender());
68 visitor_->IsDisplayNode(false);
69 nodeName = surfaceNode->GetName();
70 } else if (auto displayNode = node->ReinterpretCastTo<RSLogicalDisplayRenderNode>()) {
71 auto screenInfo = CreateOrGetScreenManager()->QueryScreenInfo(displayNode->GetScreenId());
72 GraphicColorGamut colorGamut = static_cast<GraphicColorGamut>(screenInfo.colorGamut);
73 if (colorGamut != GraphicColorGamut::GRAPHIC_COLOR_GAMUT_SRGB) {
74 colorSpace = RSBaseRenderEngine::ConvertColorGamutToDrawingColorSpace(colorGamut);
75 }
76 pixelmap = CreatePixelMapByDisplayNode(displayNode, visitor_->IsUniRender());
77 visitor_->IsDisplayNode(true);
78 } else {
79 RS_LOGE("RSSurfaceCaptureTask::Run: Invalid RSRenderNodeType!");
80 return false;
81 }
82 if (pixelmap == nullptr) {
83 RS_LOGE("RSSurfaceCaptureTask::Run: pixelmap == nullptr!");
84 return false;
85 }
86 #if defined(RS_ENABLE_GL) || defined(RS_ENABLE_VK)
87 auto renderContext = RSMainThread::Instance()->GetRenderEngine()->GetRenderContext();
88 auto grContext = renderContext != nullptr ? renderContext->GetSharedDrGPUContext() : nullptr;
89 RSTagTracker tagTracker(grContext, node->GetId(), RSTagTracker::TAGTYPE::TAG_CAPTURE, nodeName);
90 #endif
91 auto surface = CreateSurface(pixelmap, colorSpace);
92 if (surface == nullptr) {
93 RS_LOGE("RSSurfaceCaptureTask::Run: surface is nullptr!");
94 return false;
95 }
96 visitor_->SetSurface(surface.get());
97 node->Process(visitor_);
98 #if (defined (RS_ENABLE_GL) || defined (RS_ENABLE_VK)) && (defined RS_ENABLE_EGLIMAGE)
99 std::shared_ptr<Drawing::Image> img(surface.get()->GetImageSnapshot());
100 if (!img) {
101 RS_LOGE("RSSurfaceCaptureTask::Run: img is nullptr");
102 return false;
103 }
104 if (!CopyDataToPixelMap(img, pixelmap)) {
105 RS_LOGE("RSSurfaceCaptureTask::Run: CopyDataToPixelMap failed");
106 return false;
107 }
108 #endif
109 // To get dump image
110 // execute "param set rosen.dumpsurfacetype.enabled 3 && setenforce 0"
111 RSBaseRenderUtil::WritePixelMapToPng(*pixelmap);
112 if (callback) {
113 callback->OnSurfaceCapture(nodeId_, captureConfig_, pixelmap.get());
114 }
115 return true;
116 }
117
CreatePixelMapBySurfaceNode(std::shared_ptr<RSSurfaceRenderNode> node,bool isUniRender)118 std::unique_ptr<Media::PixelMap> RSSurfaceCaptureTask::CreatePixelMapBySurfaceNode(
119 std::shared_ptr<RSSurfaceRenderNode> node, bool isUniRender)
120 {
121 if (node == nullptr) {
122 RS_LOGE("RSSurfaceCaptureTask::CreatePixelMapBySurfaceNode: node == nullptr");
123 return nullptr;
124 }
125 if (!isUniRender && node->GetRSSurfaceHandler()->GetBuffer() == nullptr) {
126 RS_LOGE("RSSurfaceCaptureTask::CreatePixelMapBySurfaceNode: node GetBuffer == nullptr");
127 return nullptr;
128 }
129 const auto& property = node->GetRenderProperties();
130 int pixmapWidth = property.GetBoundsWidth();
131 int pixmapHeight = property.GetBoundsHeight();
132 Media::InitializationOptions opts;
133 opts.size.width = ceil(pixmapWidth * captureConfig_.scaleX);
134 opts.size.height = ceil(pixmapHeight * captureConfig_.scaleY);
135 RS_LOGD("RSSurfaceCaptureTask::CreatePixelMapBySurfaceNode: NodeId:[%{public}" PRIu64 "],"
136 " origin pixelmap width is [%{public}u], height is [%{public}u],"
137 " created pixelmap width is [%{public}u], height is [%{public}u],"
138 " the scale is scaleY:[%{public}f], scaleY:[%{public}f]",
139 node->GetId(), pixmapWidth, pixmapHeight, opts.size.width, opts.size.height,
140 captureConfig_.scaleX, captureConfig_.scaleY);
141 return Media::PixelMap::Create(opts);
142 }
143
CreatePixelMapByDisplayNode(std::shared_ptr<RSLogicalDisplayRenderNode> node,bool isUniRender)144 std::unique_ptr<Media::PixelMap> RSSurfaceCaptureTask::CreatePixelMapByDisplayNode(
145 std::shared_ptr<RSLogicalDisplayRenderNode> node, bool isUniRender)
146 {
147 if (node == nullptr) {
148 RS_LOGE("RSSurfaceCaptureTask::CreatePixelMapByDisplayNode: node is nullptr");
149 return nullptr;
150 }
151 uint64_t screenId = node->GetScreenId();
152 RSScreenModeInfo screenModeInfo;
153 sptr<RSScreenManager> screenManager = CreateOrGetScreenManager();
154 if (!screenManager) {
155 RS_LOGE("RSSurfaceCaptureTask::CreatePixelMapByDisplayNode: screenManager is nullptr!");
156 return nullptr;
157 }
158 auto screenInfo = screenManager->QueryScreenInfo(screenId);
159 uint32_t pixmapWidth = screenInfo.width;
160 uint32_t pixmapHeight = screenInfo.height;
161 if (!isUniRender) {
162 auto rotation = node->GetRotation();
163 if (rotation == ScreenRotation::ROTATION_90 || rotation == ScreenRotation::ROTATION_270) {
164 std::swap(pixmapWidth, pixmapHeight);
165 }
166 }
167 Media::InitializationOptions opts;
168 opts.size.width = ceil(pixmapWidth * captureConfig_.scaleX);
169 opts.size.height = ceil(pixmapHeight * captureConfig_.scaleY);
170 RS_LOGI("RSSurfaceCaptureTask::CreatePixelMapByDisplayNode: NodeId:[%{public}" PRIu64 "],"
171 " origin pixelmap width is [%{public}u], height is [%{public}u],"
172 " created pixelmap width is [%{public}u], height is [%{public}u],"
173 " the scale is scaleY:[%{public}f], scaleY:[%{public}f],",
174 node->GetId(), pixmapWidth, pixmapHeight, opts.size.width, opts.size.height,
175 captureConfig_.scaleX, captureConfig_.scaleY);
176 return Media::PixelMap::Create(opts);
177 }
178
CopyDataToPixelMap(std::shared_ptr<Drawing::Image> img,const std::unique_ptr<Media::PixelMap> & pixelmap)179 bool CopyDataToPixelMap(std::shared_ptr<Drawing::Image> img, const std::unique_ptr<Media::PixelMap>& pixelmap)
180 {
181 if (!img || !pixelmap) {
182 RS_LOGE("RSSurfaceCaptureTask::CopyDataToPixelMap failed, img or pixelmap is nullptr");
183 return false;
184 }
185 auto size = pixelmap->GetRowBytes() * pixelmap->GetHeight();
186 auto colorType = (pixelmap->GetPixelFormat() == Media::PixelFormat::RGBA_F16) ?
187 Drawing::ColorType::COLORTYPE_RGBA_F16 : Drawing::ColorType::COLORTYPE_RGBA_8888;
188 #ifdef ROSEN_OHOS
189 int fd = AshmemCreate("RSSurfaceCapture Data", size);
190 if (fd < 0) {
191 RS_LOGE("RSSurfaceCaptureTask::CopyDataToPixelMap AshmemCreate fd < 0");
192 return false;
193 }
194 int result = AshmemSetProt(fd, PROT_READ | PROT_WRITE);
195 if (result < 0) {
196 RS_LOGE("RSSurfaceCaptureTask::CopyDataToPixelMap AshmemSetProt error");
197 ::close(fd);
198 return false;
199 }
200 void* ptr = ::mmap(nullptr, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
201 auto data = static_cast<uint8_t*>(ptr);
202 if (ptr == MAP_FAILED || ptr == nullptr) {
203 RS_LOGE("RSSurfaceCaptureTask::CopyDataToPixelMap data is nullptr");
204 ::close(fd);
205 return false;
206 }
207
208 Drawing::BitmapFormat format { colorType, Drawing::AlphaType::ALPHATYPE_PREMUL };
209 Drawing::Bitmap bitmap;
210 auto colorSpaceName = pixelmap->InnerGetGrColorSpace().GetColorSpaceName();
211 auto colorSpace = RSBaseRenderEngine::ConvertColorSpaceNameToDrawingColorSpace(colorSpaceName);
212 bitmap.Build(pixelmap->GetWidth(), pixelmap->GetHeight(), format, 0, colorSpace);
213 bitmap.SetPixels(data);
214 if (!img->ReadPixels(bitmap, 0, 0)) {
215 RS_LOGE("RSSurfaceCaptureTask::CopyDataToPixelMap readPixels failed");
216 ::close(fd);
217 return false;
218 }
219 void* fdPtr = new int32_t();
220 *static_cast<int32_t*>(fdPtr) = fd;
221 pixelmap->SetPixelsAddr(data, fdPtr, size, Media::AllocatorType::SHARE_MEM_ALLOC, nullptr);
222 #else
223 auto data = (uint8_t *)malloc(size);
224 if (data == nullptr) {
225 RS_LOGE("RSSurfaceCaptureTask::CopyDataToPixelMap data is nullptr");
226 return false;
227 }
228
229 Drawing::BitmapFormat format { colorType, Drawing::AlphaType::ALPHATYPE_PREMUL };
230 Drawing::Bitmap bitmap;
231 bitmap.Build(pixelmap->GetWidth(), pixelmap->GetHeight(), format, 0, colorSpace);
232 bitmap.SetPixels(data);
233 if (!img->ReadPixels(bitmap, 0, 0)) {
234 RS_LOGE("RSSurfaceCaptureTask::CopyDataToPixelMap readPixels failed");
235 free(data);
236 data = nullptr;
237 return false;
238 }
239
240 pixelmap->SetPixelsAddr(data, nullptr, size, Media::AllocatorType::HEAP_ALLOC, nullptr);
241 #endif
242 return true;
243 }
244
CreateSurface(const std::unique_ptr<Media::PixelMap> & pixelmap,std::shared_ptr<Drawing::ColorSpace> colorSpace)245 std::shared_ptr<Drawing::Surface> RSSurfaceCaptureTask::CreateSurface(
246 const std::unique_ptr<Media::PixelMap>& pixelmap, std::shared_ptr<Drawing::ColorSpace> colorSpace)
247 {
248 if (pixelmap == nullptr) {
249 RS_LOGE("RSSurfaceCaptureTask::CreateSurface: pixelmap == nullptr");
250 return nullptr;
251 }
252 auto address = const_cast<uint32_t*>(pixelmap->GetPixel32(0, 0));
253 if (address == nullptr) {
254 RS_LOGE("RSSurfaceCaptureTask::CreateSurface: address == nullptr");
255 return nullptr;
256 }
257 Drawing::ImageInfo info = Drawing::ImageInfo{pixelmap->GetWidth(), pixelmap->GetHeight(),
258 Drawing::ColorType::COLORTYPE_RGBA_8888, Drawing::AlphaType::ALPHATYPE_PREMUL, colorSpace};
259
260 #if (defined RS_ENABLE_GL) && (defined RS_ENABLE_EGLIMAGE)
261 if (RSSystemProperties::GetGpuApiType() == GpuApiType::OPENGL) {
262 auto renderContext = RSMainThread::Instance()->GetRenderEngine()->GetRenderContext();
263 if (renderContext == nullptr) {
264 RS_LOGE("RSSurfaceCaptureTask::CreateSurface: renderContext is nullptr");
265 return nullptr;
266 }
267 renderContext->SetUpGpuContext(nullptr);
268 return Drawing::Surface::MakeRenderTarget(renderContext->GetDrGPUContext(), false, info);
269 }
270 #endif
271 #ifdef RS_ENABLE_VK
272 if (RSSystemProperties::IsUseVulkan()) {
273 return Drawing::Surface::MakeRenderTarget(
274 RSMainThread::Instance()->GetRenderEngine()->GetSkContext().get(), false, info);
275 }
276 #endif
277 return Drawing::Surface::MakeRasterDirect(info, address, pixelmap->GetRowBytes());
278 }
279
RSSurfaceCaptureVisitor(const RSSurfaceCaptureConfig & captureConfig,bool isUniRender)280 RSSurfaceCaptureVisitor::RSSurfaceCaptureVisitor(const RSSurfaceCaptureConfig& captureConfig, bool isUniRender)
281 : captureConfig_(captureConfig), isUniRender_(isUniRender)
282 {
283 renderEngine_ = RSMainThread::Instance()->GetRenderEngine();
284 }
285
SetSurface(Drawing::Surface * surface)286 void RSSurfaceCaptureVisitor::SetSurface(Drawing::Surface* surface)
287 {
288 if (surface == nullptr) {
289 RS_LOGE("RSSurfaceCaptureVisitor::SetSurface: surface == nullptr");
290 return;
291 }
292 canvas_ = std::make_unique<RSPaintFilterCanvas>(surface);
293 canvas_->Scale(captureConfig_.scaleX, captureConfig_.scaleY);
294 canvas_->SetDisableFilterCache(true);
295 }
296
ProcessChildren(RSRenderNode & node)297 void RSSurfaceCaptureVisitor::ProcessChildren(RSRenderNode &node)
298 {
299 for (auto& child : *node.GetSortedChildren()) {
300 if (!child) {
301 continue;
302 }
303 child->Process(shared_from_this());
304 }
305 }
306
ProcessScreenRenderNode(RSScreenRenderNode & node)307 void RSSurfaceCaptureVisitor::ProcessScreenRenderNode(RSScreenRenderNode &node)
308 {
309 RS_TRACE_NAME("RSSurfaceCaptureVisitor::ProcessScreenRenderNode:" +
310 std::to_string(node.GetId()));
311 RS_LOGD("RSSurfaceCaptureVisitor::ProcessScreenRenderNode child size:[%{public}d] total",
312 node.GetChildrenCount());
313
314 if (canvas_ == nullptr) {
315 RS_LOGE("RSSurfaceCaptureVisitor::ProcessScreenRenderNode: Canvas is null!");
316 return;
317 }
318
319 ProcessChildren(node);
320 }
321
ProcessLogicalDisplayRenderNode(RSLogicalDisplayRenderNode & node)322 void RSSurfaceCaptureVisitor::ProcessLogicalDisplayRenderNode(RSLogicalDisplayRenderNode& node)
323 {
324 ProcessChildren(node);
325 }
326
CaptureSingleSurfaceNodeWithoutUni(RSSurfaceRenderNode & node)327 void RSSurfaceCaptureVisitor::CaptureSingleSurfaceNodeWithoutUni(RSSurfaceRenderNode& node)
328 {
329 Drawing::Matrix translateMatrix;
330 auto parentPtr = node.GetParent().lock();
331 if (parentPtr != nullptr && parentPtr->IsInstanceOf<RSSurfaceRenderNode>()) {
332 // calculate the offset from this node's parent, and perform translate.
333 auto parentNode = std::static_pointer_cast<RSSurfaceRenderNode>(parentPtr);
334 const float parentNodeTranslateX = parentNode->GetTotalMatrix().Get(Drawing::Matrix::Index::TRANS_X);
335 const float parentNodeTranslateY = parentNode->GetTotalMatrix().Get(Drawing::Matrix::Index::TRANS_Y);
336 const float thisNodetranslateX = node.GetTotalMatrix().Get(Drawing::Matrix::Index::TRANS_X);
337 const float thisNodetranslateY = node.GetTotalMatrix().Get(Drawing::Matrix::Index::TRANS_Y);
338 translateMatrix.PreTranslate(
339 thisNodetranslateX - parentNodeTranslateX, thisNodetranslateY - parentNodeTranslateY);
340 }
341 if (node.GetSpecialLayerMgr().Find(SpecialLayerType::SECURITY) ||
342 node.GetSpecialLayerMgr().Find(SpecialLayerType::SKIP)) {
343 RS_LOGD("RSSurfaceCaptureVisitor::CaptureSingleSurfaceNodeWithoutUni: \
344 process RSSurfaceRenderNode(id:[%{public}" PRIu64 "]) clear white since it is security layer.",
345 node.GetId());
346 Drawing::AutoCanvasRestore acr(*canvas_.get(), true);
347 canvas_->ConcatMatrix(translateMatrix);
348 canvas_->Clear(Drawing::Color::COLOR_WHITE);
349 return;
350 }
351
352 if (node.GetChildrenCount() > 0) {
353 canvas_->ConcatMatrix(translateMatrix);
354 const auto saveCnt = canvas_->Save();
355 ProcessChildren(node);
356 canvas_->RestoreToCount(saveCnt);
357 if (node.GetRSSurfaceHandler()->GetBuffer() != nullptr) {
358 // in node's local coordinate.
359 auto params = RSDividedRenderUtil::CreateBufferDrawParam(node, true, false, false, false);
360 renderEngine_->DrawSurfaceNodeWithParams(*canvas_, node, params);
361 }
362 } else {
363 Drawing::AutoCanvasRestore acr(*canvas_.get(), true);
364 canvas_->ConcatMatrix(translateMatrix);
365 if (node.GetRSSurfaceHandler()->GetBuffer() != nullptr) {
366 // in node's local coordinate.
367 auto params = RSDividedRenderUtil::CreateBufferDrawParam(node, true, false, false, false);
368 renderEngine_->DrawSurfaceNodeWithParams(*canvas_, node, params);
369 }
370 }
371 }
372
CaptureSurfaceInDisplayWithoutUni(RSSurfaceRenderNode & node)373 void RSSurfaceCaptureVisitor::CaptureSurfaceInDisplayWithoutUni(RSSurfaceRenderNode& node)
374 {
375 if (node.GetSpecialLayerMgr().Find(SpecialLayerType::SECURITY) ||
376 node.GetSpecialLayerMgr().Find(SpecialLayerType::SKIP)) {
377 RS_LOGD("RSSurfaceCaptureVisitor::CaptureSurfaceInDisplayWithoutUni: \
378 process RSSurfaceRenderNode(id:[%{public}" PRIu64 "]) paused since it is security layer.",
379 node.GetId());
380 return;
381 }
382 ProcessChildren(node);
383 if (node.GetRSSurfaceHandler()->GetBuffer() != nullptr) {
384 // in display's coordinate.
385 auto params = RSDividedRenderUtil::CreateBufferDrawParam(node, false, false, false, false);
386 renderEngine_->DrawSurfaceNodeWithParams(*canvas_, node, params);
387 }
388 }
389
ProcessSurfaceRenderNodeWithoutUni(RSSurfaceRenderNode & node)390 void RSSurfaceCaptureVisitor::ProcessSurfaceRenderNodeWithoutUni(RSSurfaceRenderNode& node)
391 {
392 if (isDisplayNode_) {
393 CaptureSurfaceInDisplayWithoutUni(node);
394 } else {
395 CaptureSingleSurfaceNodeWithoutUni(node);
396 }
397 }
398
ProcessSurfaceRenderNode(RSSurfaceRenderNode & node)399 void RSSurfaceCaptureVisitor::ProcessSurfaceRenderNode(RSSurfaceRenderNode &node)
400 {
401 RS_TRACE_NAME("RSSurfaceCaptureVisitor::Process:" + node.GetName());
402
403 if (canvas_ == nullptr) {
404 RS_LOGE("RSSurfaceCaptureVisitor::ProcessSurfaceRenderNode, canvas is nullptr");
405 return;
406 }
407
408 if (!node.ShouldPaint()) {
409 RS_LOGD("RSSurfaceCaptureVisitor::ProcessSurfaceRenderNode node: %{public}" PRIu64 " invisible", node.GetId());
410 return;
411 }
412
413 ProcessSurfaceRenderNodeWithoutUni(node);
414 }
415 } // namespace Rosen
416 } // namespace OHOS
417