• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2025 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_capture_pixelmap_manager.h"
17 #include "draw/color.h"
18 #include "image/bitmap.h"
19 #include "platform/common/rs_log.h"
20 #include <memory>
21 #include <mutex>
22 #include "rs_trace.h"
23 #ifdef ROSEN_OHOS
24 #include <sys/mman.h>
25 #include "parameters.h"
26 #endif
27 
28 #if defined (RS_ENABLE_UNI_RENDER) && defined (ROSEN_OHOS) && defined(RS_ENABLE_VK)
29 #include "draw/surface.h"
30 #include "surface_buffer.h"
31 #endif
32 
33 #ifdef RS_ENABLE_VK
34 #include "platform/ohos/backend/native_buffer_utils.h"
35 #endif
36 
37 namespace OHOS {
38 namespace Rosen {
39 CapturePixelMapMemFunHandle RSCapturePixelMapManager::funcHandle_;
40 CapturePixelMapCheckFunHandle RSCapturePixelMapManager::checkHandle_;
41 
42 /**
43  * @brief Define pixelMap Attach Mem
44 **/
LoadCheckFunc()45 void RSCapturePixelMapManager::LoadCheckFunc()
46 {
47     checkHandle_[uint32UniRenderDisableType_][uint32DefaultCaptureType_] = [](const Drawing::Rect& areaRect,
48         const RSSurfaceCaptureConfig& captureConfig) {
49         return true;
50     };
51 
52     checkHandle_[uint32UniRenderDisableType_][uint32UiCaptureType_] = [](const Drawing::Rect& areaRect,
53         const RSSurfaceCaptureConfig& captureConfig) {
54         return true;
55     };
56 
57     checkHandle_[uint32UniRenderEnableType_][uint32DefaultCaptureType_] = [](const Drawing::Rect& areaRect,
58         const RSSurfaceCaptureConfig& captureConfig) {
59         if (captureConfig.scaleX > 1.f || captureConfig.scaleY > 1.f) {
60             return false;
61         }
62         return true;
63     };
64 
65     checkHandle_[uint32UniRenderEnableType_][uint32UiCaptureType_] = [](const Drawing::Rect& areaRect,
66         const RSSurfaceCaptureConfig& captureConfig) {
67 #ifdef RS_ENABLE_VK
68         int32_t width = ceil(areaRect.GetWidth() * captureConfig.scaleX);
69         int32_t height = ceil(areaRect.GetHeight() * captureConfig.scaleY);
70         if (width > 0 && static_cast<int32_t>(OHOS::Rosen::NativeBufferUtils::VKIMAGE_LIMIT_SIZE) / width < height) {
71             RS_LOGE("RSUiCaptureTaskParallel::CreateResources:image is too large, width:%{public}d,height::%{public}d",
72                 width, height);
73             return false;
74         }
75 #endif
76         return true;
77     };
78 }
79 
LoadSetMemFunc()80 void RSCapturePixelMapManager::LoadSetMemFunc()
81 {
82     funcHandle_[uint32UniRenderDisableType_][uint32DefaultCaptureType_] = AttachCommMem;
83     funcHandle_[uint32UniRenderDisableType_][uint32UiCaptureType_] = AttachShareMem;
84 
85     funcHandle_[uint32UniRenderEnableType_][uint32DefaultCaptureType_] = AttachUniCommMem;
86     funcHandle_[uint32UniRenderEnableType_][uint32UiCaptureType_] = AttachUniCommMem;
87 }
88 
SetCapturePixelMapMem(const std::unique_ptr<Media::PixelMap> & pixelmap,const SurfaceCaptureType & captureType,const UniRenderEnabledType & uniRenderEnabledType,bool useDma)89 bool RSCapturePixelMapManager::SetCapturePixelMapMem(const std::unique_ptr<Media::PixelMap>& pixelmap,
90     const SurfaceCaptureType& captureType, const UniRenderEnabledType& uniRenderEnabledType, bool useDma)
91 {
92     if (pixelmap == nullptr) {
93         return false;
94     }
95     // Init Policy Function
96     static std::once_flag LoadSetMemFunFlag;
97     std::call_once(LoadSetMemFunFlag, []()
98     {
99         RSCapturePixelMapManager::LoadSetMemFunc();
100     });
101 
102     auto tempCaptureType = static_cast<uint32_t>(captureType);
103     auto tmpUniRenderType = static_cast<uint32_t>(uniRenderEnabledType);
104     auto iter = funcHandle_.find(tmpUniRenderType);
105     if (iter != funcHandle_.end() && iter->second.find(tempCaptureType) != iter->second.end()) {
106         return funcHandle_[tmpUniRenderType][tempCaptureType](pixelmap, useDma);
107     }
108     return false;
109 }
110 
CheckCaptureConfig(const Drawing::Rect & areaRect,const RSSurfaceCaptureConfig & captureConfig,const UniRenderEnabledType & uniRenderEnabledType)111 bool RSCapturePixelMapManager::CheckCaptureConfig(const Drawing::Rect& areaRect,
112     const RSSurfaceCaptureConfig& captureConfig, const UniRenderEnabledType& uniRenderEnabledType)
113 {
114     if (ROSEN_EQ(captureConfig.scaleX, 0.f) || ROSEN_EQ(captureConfig.scaleY, 0.f) ||
115         captureConfig.scaleX < 0.f || captureConfig.scaleY < 0.f) {
116         return false;
117     }
118     auto tempCaptureType = static_cast<uint32_t>(captureConfig.captureType);
119     auto tmpUniRenderType = static_cast<uint32_t>(uniRenderEnabledType);
120     auto iter = checkHandle_.find(tmpUniRenderType);
121     if (iter != checkHandle_.end() && iter->second.find(tempCaptureType) != iter->second.end()) {
122         return checkHandle_[tmpUniRenderType][tempCaptureType](areaRect, captureConfig);
123     }
124     return false;
125 }
126 
CopyDataToPixelMap(std::shared_ptr<Drawing::Image> img,const std::unique_ptr<Media::PixelMap> & pixelmap,std::shared_ptr<Drawing::ColorSpace> colorSpace)127 bool RSCapturePixelMapManager::CopyDataToPixelMap(std::shared_ptr<Drawing::Image> img,
128     const std::unique_ptr<Media::PixelMap>& pixelmap, std::shared_ptr<Drawing::ColorSpace> colorSpace)
129 {
130     if (img == nullptr || pixelmap == nullptr) {
131         RS_LOGE("RSCapturePixelMapManager::CopyDataToPixelMap img or pixelmap is nullptr");
132         return false;
133     }
134 
135     uint8_t* pixelMapData = const_cast<uint8_t*>(pixelmap->GetPixels());
136     if (pixelMapData == nullptr) {
137         RS_LOGE("RSCapturePixelMapManager::CopyDataToPixelMap pixelMapData is nullptr");
138         return false;
139     }
140     Drawing::BitmapFormat format { Drawing::ColorType::COLORTYPE_RGBA_8888, Drawing::AlphaType::ALPHATYPE_PREMUL };
141     Drawing::Bitmap bitmap;
142     bitmap.Build(pixelmap->GetWidth(), pixelmap->GetHeight(), format, 0, colorSpace);
143     bitmap.SetPixels(pixelMapData);
144     if (!img->ReadPixels(bitmap, 0, 0)) {
145         RS_LOGE("RSCapturePixelMapManager::CopyDataToPixelMap readPixels failed");
146         return false;
147     }
148 
149     return true;
150 }
151 
CopyDataToPixelMap(std::shared_ptr<Drawing::Image> img,const std::unique_ptr<Media::PixelMap> & pixelmap)152 bool RSCapturePixelMapManager::CopyDataToPixelMap(std::shared_ptr<Drawing::Image> img,
153     const std::unique_ptr<Media::PixelMap>& pixelmap)
154 {
155     if (img == nullptr || pixelmap == nullptr) {
156         return false;
157     }
158     uint8_t* pixelMapData = const_cast<uint8_t*>(pixelmap->GetPixels());
159     if (pixelMapData == nullptr) {
160         RS_LOGE("RSCapturePixelMapManager::CopyDataToPixelMap pixelMapData is nullptr");
161         return false;
162     }
163     Drawing::ImageInfo info = Drawing::ImageInfo(pixelmap->GetWidth(), pixelmap->GetHeight(),
164         Drawing::ColorType::COLORTYPE_RGBA_8888, Drawing::AlphaType::ALPHATYPE_PREMUL);
165     if (!img->ReadPixels(info, pixelMapData, pixelmap->GetRowBytes(), 0, 0)) {
166         RS_LOGE("RSUniUICapture::CopyDataToPixelMap readPixels failed");
167         return false;
168     }
169     return true;
170 }
171 
GetCaptureAreaRect(const Drawing::Rect & nodeAreaRect,const Drawing::Rect & specifiedAreaRect,const SurfaceCaptureType & captureType)172 Drawing::Rect RSCapturePixelMapManager::GetCaptureAreaRect(const Drawing::Rect& nodeAreaRect,
173     const Drawing::Rect& specifiedAreaRect, const SurfaceCaptureType& captureType)
174 {
175     if (captureType == SurfaceCaptureType::DEFAULT_CAPTURE || !specifiedAreaRect.IsValid()) {
176         return nodeAreaRect;
177     }
178     // nodeAreaRect is node weight and height, left and rigth = 0
179     if ((specifiedAreaRect.GetWidth() > nodeAreaRect.GetWidth()) ||
180         (specifiedAreaRect.GetHeight() > nodeAreaRect.GetHeight()) ||
181         (specifiedAreaRect.GetLeft() < 0) || (specifiedAreaRect.GetTop() < 0) ||
182         (specifiedAreaRect.GetRight() > nodeAreaRect.GetWidth()) ||
183         (specifiedAreaRect.GetBottom() > nodeAreaRect.GetHeight())) {
184         RS_LOGE("RSCapturePixelMapManager::GetCaptureAreaRect: specifiedAreaRect is out of bounds");
185         return nodeAreaRect;
186     }
187     return specifiedAreaRect;
188 }
189 
GetClientCapturePixelMap(const Drawing::Rect & nodeAreaRect,const RSSurfaceCaptureConfig & captureConfig,const UniRenderEnabledType & uniRenderEnabledType,const Drawing::Rect & specifiedAreaRect)190 std::unique_ptr<Media::PixelMap> RSCapturePixelMapManager::GetClientCapturePixelMap(const Drawing::Rect& nodeAreaRect,
191     const RSSurfaceCaptureConfig& captureConfig, const UniRenderEnabledType& uniRenderEnabledType,
192     const Drawing::Rect& specifiedAreaRect)
193 {
194     if (uniRenderEnabledType == UniRenderEnabledType::UNI_RENDER_DISABLED) {
195         return nullptr;
196     }
197     Drawing::Rect pixelMapArea = GetCaptureAreaRect(nodeAreaRect, specifiedAreaRect, captureConfig.captureType);
198 
199     auto pixelMap = GetCapturePixelMap(pixelMapArea, captureConfig, uniRenderEnabledType);
200     if (pixelMap == nullptr) {
201         return nullptr;
202     }
203     if (!SetCapturePixelMapMem(pixelMap, captureConfig.captureType, uniRenderEnabledType, captureConfig.useDma)) {
204         RS_LOGE("RSCapturePixelMapManager::GetClientCapturePixelMap SetCapturePixelMapMem failed");
205         return nullptr;
206     }
207     return pixelMap;
208 }
209 
GetCapturePixelMap(const Drawing::Rect & areaRect,const RSSurfaceCaptureConfig & captureConfig,const UniRenderEnabledType & uniRenderEnabledType)210 std::unique_ptr<Media::PixelMap> RSCapturePixelMapManager::GetCapturePixelMap(const Drawing::Rect& areaRect,
211     const RSSurfaceCaptureConfig& captureConfig, const UniRenderEnabledType& uniRenderEnabledType)
212 {
213     // Init Policy Function
214     static std::once_flag LoadCheckFunFlag;
215     std::call_once(LoadCheckFunFlag, []() {
216         RSCapturePixelMapManager::LoadCheckFunc();
217     });
218 
219     if (!CheckCaptureConfig(areaRect, captureConfig, uniRenderEnabledType)) {
220         return nullptr;
221     }
222     return CreatePixelMap(areaRect, captureConfig);
223 }
224 
CreatePixelMap(const Drawing::Rect & areaRect,const RSSurfaceCaptureConfig & captureConfig)225 std::unique_ptr<Media::PixelMap> RSCapturePixelMapManager::CreatePixelMap(const Drawing::Rect& areaRect,
226     const RSSurfaceCaptureConfig& captureConfig)
227 {
228     float pixelMapWidth = areaRect.GetWidth();
229     float pixelMapHeight = areaRect.GetHeight();
230     Media::InitializationOptions opts;
231     opts.size.width = ceil(pixelMapWidth * captureConfig.scaleX);
232     opts.size.height = ceil(pixelMapHeight * captureConfig.scaleY);
233     RS_LOGD("RSCapturePixelMapManager::CreatePixelMap:"
234         " origin pixelmap width is [%{public}f], height is [%{public}f],"
235         " created pixelmap width is [%{public}u], height is [%{public}u],"
236         " the scale is scaleX:[%{public}f], scaleY:[%{public}f]",
237         pixelMapWidth, pixelMapHeight, opts.size.width, opts.size.height,
238         captureConfig.scaleX, captureConfig.scaleY);
239 
240     return Media::PixelMap::Create(opts);
241 }
242 
AttachUniCommMem(const std::unique_ptr<Media::PixelMap> & pixelMap,bool isUsedDma)243 bool RSCapturePixelMapManager::AttachUniCommMem(const std::unique_ptr<Media::PixelMap>& pixelMap, bool isUsedDma)
244 {
245 #if defined (RS_ENABLE_UNI_RENDER) && defined (ROSEN_OHOS) && defined(RS_ENABLE_VK)
246     if ((RSSystemProperties::GetGpuApiType() == GpuApiType::VULKAN ||
247         RSSystemProperties::GetGpuApiType() == GpuApiType::DDGR) && isUsedDma) {
248         return RSCapturePixelMapManager::AttachDmaMem(pixelMap);
249     }
250 #endif
251 
252 #ifdef ROSEN_OHOS
253     return AttachShareMem(pixelMap);
254 #endif
255     return AttachHeapMem(pixelMap);
256 }
257 
AttachCommMem(const std::unique_ptr<Media::PixelMap> & pixelMap,bool isUsedDma)258 bool RSCapturePixelMapManager::AttachCommMem(const std::unique_ptr<Media::PixelMap>& pixelMap, bool isUsedDma)
259 {
260     (void)isUsedDma;
261 #ifdef ROSEN_OHOS
262     return AttachShareMem(pixelMap);
263 #endif
264     return AttachHeapMem(pixelMap);
265 }
266 
AttachShareMem(const std::unique_ptr<Media::PixelMap> & pixelMap,bool isUsedDma)267 bool RSCapturePixelMapManager::AttachShareMem(const std::unique_ptr<Media::PixelMap>& pixelMap, bool isUsedDma)
268 {
269     // unused
270     (void)isUsedDma;
271 #if (defined (RS_ENABLE_GL) || defined (RS_ENABLE_VK)) && (defined RS_ENABLE_EGLIMAGE) && (defined ROSEN_OHOS)
272     auto size = pixelMap->GetRowBytes() * pixelMap->GetHeight();
273     int fd = AshmemCreate("RSSurfaceCapture Data", size);
274     if (fd < 0) {
275         RS_LOGE("RSCapturePixelMapManager::AttachShareMem AshmemCreate fd < 0");
276         return false;
277     }
278     int result = AshmemSetProt(fd, PROT_READ | PROT_WRITE);
279     if (result < 0) {
280         RS_LOGE("RSCapturePixelMapManager::AttachShareMem AshmemSetProt error");
281         ::close(fd);
282         return false;
283     }
284     void* ptr = ::mmap(nullptr, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
285     auto data = static_cast<uint8_t*>(ptr);
286     if (ptr == MAP_FAILED || ptr == nullptr) {
287         RS_LOGE("RSCapturePixelMapManager::AttachShareMem data is nullptr");
288         ::close(fd);
289         return false;
290     }
291     void* fdPtr = new int32_t();
292     if (fdPtr == nullptr) {
293         ::munmap(ptr, size);
294         ::close(fd);
295         return false;
296     }
297     *static_cast<int32_t*>(fdPtr) = fd;
298     pixelMap->SetPixelsAddr(data, fdPtr, size, Media::AllocatorType::SHARE_MEM_ALLOC, nullptr);
299     RS_LOGD("RSCapturePixelMapManager::AttachShareMem Success");
300     return true;
301 #else
302     RS_LOGE("RSCapturePixelMapManager::AttachShareMem Unsupport AttachShareMem");
303     return false;
304 #endif
305 }
306 
AttachHeapMem(const std::unique_ptr<Media::PixelMap> & pixelMap)307 bool RSCapturePixelMapManager::AttachHeapMem(const std::unique_ptr<Media::PixelMap>& pixelMap)
308 {
309 #if (defined (RS_ENABLE_GL) || defined (RS_ENABLE_VK)) && (defined RS_ENABLE_EGLIMAGE)
310     auto size = pixelMap->GetRowBytes() * pixelMap->GetHeight();
311     auto data = (uint8_t *)malloc(size);
312     if (data == nullptr) {
313         RS_LOGE("RSCapturePixelMapManager::AttachHeapMem data is nullptr");
314         return false;
315     }
316     pixelMap->SetPixelsAddr(data, nullptr, size, Media::AllocatorType::HEAP_ALLOC, nullptr);
317     RS_LOGI("RSCapturePixelMapManager::AttachHeapMem Success");
318     return true;
319 #else
320     RS_LOGE("RSCapturePixelMapManager::AttachHeapMem Unsupport AttachHeapMem");
321     return false;
322 #endif
323 }
324 
325 
AttachDmaMem(const std::unique_ptr<Media::PixelMap> & pixelMap)326 bool RSCapturePixelMapManager::AttachDmaMem(const std::unique_ptr<Media::PixelMap>& pixelMap)
327 {
328 #if defined(_WIN32) || defined(_APPLE) || defined(A_PLATFORM) || defined(IOS_PLATFORM)
329     RS_LOGE("RSCapturePixelMapManager::AttachDmaMem Unsupport dma mem alloc");
330     return false;
331 #elif defined (RS_ENABLE_UNI_RENDER) && defined (ROSEN_OHOS) && defined(RS_ENABLE_VK)
332     if (pixelMap == nullptr) {
333         RS_LOGE("RSCapturePixelMapManager::AttachDmaMem: pixelmap is nullptr");
334         return false;
335     }
336     sptr<SurfaceBuffer> surfaceBuffer = SurfaceBuffer::Create();
337     if (!surfaceBuffer) {
338         RS_LOGE("RSCapturePixelMapManager::AttachDmaMem: surfaceBuffer create failed");
339         return false;
340     }
341     BufferRequestConfig requestConfig = {
342         .width = pixelMap->GetWidth(),
343         .height = pixelMap->GetHeight(),
344         .strideAlignment = 0x8, // set 0x8 as default value to alloc SurfaceBufferImpl
345         .format = GRAPHIC_PIXEL_FMT_RGBA_8888, // PixelFormat
346         .usage = BUFFER_USAGE_CPU_READ | BUFFER_USAGE_HW_RENDER | BUFFER_USAGE_HW_TEXTURE |
347             BUFFER_USAGE_MEM_DMA | BUFFER_USAGE_MEM_MMZ_CACHE,
348         .timeout = 0,
349         .colorGamut = GraphicColorGamut::GRAPHIC_COLOR_GAMUT_SRGB,
350         .transform = GraphicTransformType::GRAPHIC_ROTATE_NONE,
351     };
352     GSError ret = surfaceBuffer->Alloc(requestConfig);
353     if (ret != GSERROR_OK) {
354         RS_LOGE("RSCapturePixelMapManager::AttachDmaMem: surfaceBuffer alloc failed, %{public}s",
355             GSErrorStr(ret).c_str());
356         return false;
357     }
358     void* nativeBuffer = surfaceBuffer.GetRefPtr();
359     OHOS::RefBase *ref = reinterpret_cast<OHOS::RefBase *>(nativeBuffer);
360     ref->IncStrongRef(ref);
361     int32_t bufferSize = pixelMap->GetByteCount();
362     pixelMap->SetPixelsAddr(surfaceBuffer->GetVirAddr(), nativeBuffer, bufferSize,
363         Media::AllocatorType::DMA_ALLOC, nullptr);
364     RS_LOGI("RSCapturePixelMapManager::AttachDmaMem Success");
365     return true;
366 #else
367     RS_LOGE("RSCapturePixelMapManager::AttachDmaMem Unsupport AttachDmaMem");
368     return false;
369 #endif
370 }
371 
372 } // OHOS
373 } // Rosen