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