• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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