1 /*
2 * Copyright (c) 2022-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 <algorithm>
17 #include <hitrace_meter.h>
18 #include <surface.h>
19 #include "surface_draw.h"
20 #include <transaction/rs_interfaces.h>
21 #include <ui/rs_surface_extractor.h>
22
23 #include "image/bitmap.h"
24 #include "image_source.h"
25 #include "image_type.h"
26 #include "image_utils.h"
27 #include "render/rs_pixel_map_util.h"
28 #include "surface_capture_future.h"
29 #include "window_manager_hilog.h"
30
31 namespace OHOS {
32 namespace Rosen {
33 namespace {
34 constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_WINDOW, "SurfaceDraw"};
35 constexpr uint32_t IMAGE_BYTES_STRIDE = 4;
36 constexpr float CENTER_IN_RECT = 0.5; // Multiply by 0.5 to obtain the coordinates in center
37 constexpr float FIXED_BOTTOM_SAFE_AREA_HEIGHT_VP = 28.0; // 28.0 indicates fixed bottom safe area height of windowRect
38 constexpr float FIXED_TOP_SAFE_AREA_HEIGHT_VP = 36.0; // 36.0 indicates fixed top safe srea height off windowRect
39 constexpr float MAX_BRAND_CONTENT_WIDTH_VP = 400.0; // 400.0 indicates max brand content width of windowRect
40 constexpr float MIN_BRAND_CONTENT_HEIGHT_VP = 80.0; // 80.0 indicates min brand content height of windowRect
41 constexpr float MIN_RECT_HEIGHT_VP = 100.0; // 100.0 indicates min rect height of windowRect
42 constexpr float SIDE_DISTANCE_VP = 16.0; // 16.0 indicates side distance of windowRect
43 constexpr float WIDTH_THRESHOLD_SMALL_VP = 320.0; // Small threshold, use it when windowWidth <=320
44 constexpr float WIDTH_THRESHOLD_MEDIUM_VP = 600.0; // Medium threshold, use it when windowWidth <=600
45 constexpr float WIDTH_THRESHOLD_LARGE_VP = 840.0; // Large threshold, use it when windowWidth <=840
46 constexpr float ICON_SIZE_SMALL_VP = 128.0; // 128.0 indicates small app icon sideLength
47 constexpr float ICON_SIZE_MEDIUM_VP = 192.0; // 192.0 indicates medium app icon sideLength
48 constexpr float ICON_SIZE_LARGE_VP = 256.0; // 256.0 indicates large app icon sideLength
49 constexpr float ASPECT_RATIO_1 = 9.0f / 7.2f; // windowRect Aspect ratio threshold 9 : 7.2
50 constexpr float ASPECT_RATIO_2 = 9.0f / 10.8f; // windwoRect Aspect ratio threshold 9 : 10.8
51 constexpr float EIGHTY_PERCENT = 0.8; // 0.8 indicates eighty percent
52 constexpr float FORTY_PERCENT = 0.4; // 0.4 indicates forty percent
53 constexpr float SEVENTY_PERCENT = 0.7; // 0.7 indicates seventy percent
54 constexpr float THIRTY_PERCENT = 0.3; // 0.3 indicates thirty percent
55 } // namespace
56
IsValidPixelMap(const std::shared_ptr<Media::PixelMap> & pixelMap)57 bool IsValidPixelMap(const std::shared_ptr<Media::PixelMap>& pixelMap)
58 {
59 if (pixelMap == nullptr) {
60 TLOGD(WmsLogTag::WMS_PATTERN, "pixelMap is nullptr.");
61 return false;
62 }
63 return pixelMap->GetHeight() > 0 && pixelMap->GetWidth() > 0;
64 }
65
66 template <typename T>
TryDrawResource(const std::shared_ptr<Rosen::ResourceInfo> & resource,uint32_t frameIdx,T && drawFunc,const char * resourceName)67 void TryDrawResource(const std::shared_ptr<Rosen::ResourceInfo>& resource, uint32_t frameIdx, T&& drawFunc,
68 const char* resourceName)
69 {
70 if (!resource || resource->pixelMaps.empty()) {
71 TLOGD(WmsLogTag::WMS_PATTERN, "draw failed, null resource.");
72 return;
73 }
74 uint32_t idx = (resource->pixelMaps.size() > 1) ? frameIdx : 0;
75 const auto& map = resource->pixelMaps[idx];
76 if (IsValidPixelMap(map)) {
77 if (!drawFunc(map)) {
78 TLOGD(WmsLogTag::WMS_PATTERN, "draw StartingWindow %{public}s failed.", resourceName);
79 }
80 }
81 }
82
IsValidRect(const Rect & targetRect,const Rect & winRect)83 bool IsValidRect(const Rect& targetRect, const Rect& winRect)
84 {
85 bool valid = targetRect.posX_ > 0
86 && targetRect.posY_ > 0
87 && targetRect.width_ > 0
88 && targetRect.height_ > 0
89 && (targetRect.posX_ + targetRect.width_) < winRect.width_
90 && (targetRect.posY_ + targetRect.height_) < winRect.height_;
91 return valid;
92 }
93
GetAppIconRect(const Rect & winRect,const float ratio)94 Rect GetAppIconRect(const Rect& winRect, const float ratio)
95 {
96 float width = static_cast<float>(winRect.width_);
97 float height = static_cast<float>(winRect.height_);
98 float aspectRatio = width / height;
99 float sideLen = ICON_SIZE_LARGE_VP * ratio;
100 if (width <= WIDTH_THRESHOLD_SMALL_VP * ratio) {
101 sideLen = ICON_SIZE_SMALL_VP * ratio;
102 } else if (width <= WIDTH_THRESHOLD_MEDIUM_VP * ratio) {
103 sideLen = MathHelper::GreatNotEqual(aspectRatio, ASPECT_RATIO_2) ?
104 ICON_SIZE_SMALL_VP * ratio : ICON_SIZE_MEDIUM_VP * ratio;
105 } else if (width <= WIDTH_THRESHOLD_LARGE_VP * ratio) {
106 sideLen = MathHelper::GreatNotEqual(aspectRatio, ASPECT_RATIO_1) ?
107 ICON_SIZE_MEDIUM_VP * ratio : ICON_SIZE_LARGE_VP * ratio;
108 }
109 float posX = (width - sideLen) * CENTER_IN_RECT;
110 float posY = (SEVENTY_PERCENT * height - FIXED_TOP_SAFE_AREA_HEIGHT_VP * ratio - sideLen) *
111 CENTER_IN_RECT + FIXED_TOP_SAFE_AREA_HEIGHT_VP * ratio;
112
113 Rosen::Rect appIconRect {
114 static_cast<int32_t>(posX),
115 static_cast<int32_t>(posY),
116 static_cast<uint32_t>(sideLen),
117 static_cast<uint32_t>(sideLen)
118 };
119 return appIconRect;
120 }
121
GetAboveRect(const Rect & winRect,const float ratio)122 Rect GetAboveRect(const Rect& winRect, const float ratio)
123 {
124 float width = static_cast<float>(winRect.width_);
125 float height = static_cast<float>(winRect.height_);
126
127 float axis = (height * CENTER_IN_RECT) / width;
128 float sideLen = MathHelper::GreatNotEqual(axis, 1.0f) ?
129 width * EIGHTY_PERCENT : (height * CENTER_IN_RECT) * EIGHTY_PERCENT;
130
131 float posX = (width - sideLen) * CENTER_IN_RECT;
132 float posY = (SEVENTY_PERCENT * height - FIXED_TOP_SAFE_AREA_HEIGHT_VP * ratio - sideLen) *
133 CENTER_IN_RECT + FIXED_TOP_SAFE_AREA_HEIGHT_VP * ratio;
134 Rosen::Rect aboveRect {
135 static_cast<int32_t>(posX),
136 static_cast<int32_t>(posY),
137 static_cast<uint32_t>(sideLen),
138 static_cast<uint32_t>(sideLen)
139 };
140 return aboveRect;
141 }
142
GetBelowRect(const Rect & winRect,const float ratio)143 Rect GetBelowRect(const Rect& winRect, const float ratio)
144 {
145 float width = static_cast<float>(winRect.width_);
146 float height = static_cast<float>(winRect.height_);
147
148 float rectWidth = width - 2 * SIDE_DISTANCE_VP * ratio; // 2 indicates double
149 float rectHeight = (height * THIRTY_PERCENT) * FORTY_PERCENT; // 40% height based on 30% of winRect height
150
151 Rosen::Rect belowRect { 0, 0,
152 static_cast<uint32_t>(MathHelper::Min(rectWidth, MAX_BRAND_CONTENT_WIDTH_VP * ratio)),
153 static_cast<uint32_t>(MathHelper::Max(rectHeight, MIN_BRAND_CONTENT_HEIGHT_VP * ratio))
154 };
155 belowRect.posX_ = static_cast<int32_t>((width - belowRect.width_) * CENTER_IN_RECT);
156 belowRect.posY_ = static_cast<int32_t>((height * THIRTY_PERCENT - FIXED_BOTTOM_SAFE_AREA_HEIGHT_VP * ratio -
157 belowRect.height_) * CENTER_IN_RECT + height * SEVENTY_PERCENT);
158 return belowRect;
159 }
160
FitAndDraw(const std::shared_ptr<Media::PixelMap> & pixelMap,const Rect & targetRect,Drawing::Canvas & canvas,ImageFit fit)161 void FitAndDraw(const std::shared_ptr<Media::PixelMap>& pixelMap, const Rect& targetRect,
162 Drawing::Canvas& canvas, ImageFit fit)
163 {
164 auto rsImage = std::make_shared<Rosen::RSImage>();
165 if (rsImage == nullptr) {
166 TLOGD(WmsLogTag::WMS_PATTERN, "rsImage is nullptr.");
167 return;
168 }
169 rsImage->SetPixelMap(pixelMap);
170 rsImage->SetImageFit(int(fit));
171 canvas.Save();
172 canvas.Translate(targetRect.posX_, targetRect.posY_);
173 rsImage->CanvasDrawImage(
174 canvas,
175 Drawing::Rect(
176 targetRect.posX_,
177 targetRect.posY_,
178 targetRect.posX_ + targetRect.width_,
179 targetRect.posY_ + targetRect.height_),
180 Drawing::SamplingOptions());
181 canvas.Restore();
182 }
183
DoDrawIllustration(const std::shared_ptr<Media::PixelMap> & pixelMap,const Rect & winRect,Drawing::Canvas & canvas,const float ratio,ImageFit fit)184 bool DoDrawIllustration(const std::shared_ptr<Media::PixelMap>& pixelMap, const Rect& winRect,
185 Drawing::Canvas& canvas, const float ratio, ImageFit fit)
186 {
187 auto aboveRect = GetAboveRect(winRect, ratio);
188 if (!IsValidRect(aboveRect, winRect)) {
189 TLOGD(WmsLogTag::WMS_PATTERN, "aboveRect is invalid.");
190 return false;
191 }
192 FitAndDraw(pixelMap, aboveRect, canvas, fit);
193 return true;
194 }
195
DoDrawAppIcon(const std::shared_ptr<Media::PixelMap> & pixelMap,const Rect & winRect,Drawing::Canvas & canvas,const float ratio,ImageFit fit)196 bool DoDrawAppIcon(const std::shared_ptr<Media::PixelMap>& pixelMap, const Rect& winRect,
197 Drawing::Canvas& canvas, const float ratio, ImageFit fit)
198 {
199 auto appRect = GetAppIconRect(winRect, ratio);
200 if (!IsValidRect(appRect, winRect)) {
201 TLOGD(WmsLogTag::WMS_PATTERN, "appRect is invalid.");
202 return false;
203 }
204 FitAndDraw(pixelMap, appRect, canvas, fit);
205 return true;
206 }
207
DoDrawBranding(const std::shared_ptr<Media::PixelMap> & pixelMap,const Rect & winRect,Drawing::Canvas & canvas,const float ratio,ImageFit fit)208 bool DoDrawBranding(const std::shared_ptr<Media::PixelMap>& pixelMap, const Rect& winRect,
209 Drawing::Canvas& canvas, const float ratio, ImageFit fit)
210 {
211 if ((winRect.height_ * THIRTY_PERCENT) < MIN_RECT_HEIGHT_VP * ratio) {
212 TLOGD(WmsLogTag::WMS_PATTERN, "rect is invalid.");
213 return false;
214 }
215 auto belowRect = GetBelowRect(winRect, ratio);
216 if (!IsValidRect(belowRect, winRect)) {
217 TLOGD(WmsLogTag::WMS_PATTERN, "belowRect is invalid.");
218 return false;
219 }
220 FitAndDraw(pixelMap, belowRect, canvas, fit);
221 return true;
222 }
223
DoDrawBackgroundImage(const std::shared_ptr<Media::PixelMap> & pixelMap,const Rect & winRect,Drawing::Canvas & canvas,const std::string & fit)224 bool DoDrawBackgroundImage(const std::shared_ptr<Media::PixelMap>& pixelMap, const Rect& winRect,
225 Drawing::Canvas& canvas, const std::string &fit)
226 {
227 const std::unordered_map<std::string, ImageFit> drawStrategies = {
228 { "Fill", ImageFit::FILL },
229 { "None", ImageFit::NONE },
230 { "Cover", ImageFit::COVER },
231 { "Auto", ImageFit::FIT_WIDTH },
232 { "Contain", ImageFit::CONTAIN },
233 { "ScaleDown", ImageFit::SCALE_DOWN },
234 };
235 std::string effectiveFit = fit.empty() ? "Cover" : fit;
236 auto it = drawStrategies.find(effectiveFit);
237 if (it == drawStrategies.end()) {
238 TLOGD(WmsLogTag::WMS_PATTERN, "Unsupported fit type: %{public}s", effectiveFit.c_str());
239 return false;
240 }
241 FitAndDraw(pixelMap, winRect, canvas, it->second);
242 return true;
243 }
244
DrawImage(std::shared_ptr<RSSurfaceNode> surfaceNode,int32_t bufferWidth,int32_t bufferHeight,const std::string & imagePath)245 bool SurfaceDraw::DrawImage(std::shared_ptr<RSSurfaceNode> surfaceNode, int32_t bufferWidth,
246 int32_t bufferHeight, const std::string& imagePath)
247 {
248 sptr<OHOS::Surface> layer = GetLayer(surfaceNode);
249 if (layer == nullptr) {
250 WLOGFE("layer is nullptr");
251 return false;
252 }
253 sptr<OHOS::SurfaceBuffer> buffer = GetSurfaceBuffer(layer, bufferWidth, bufferHeight);
254 if (buffer == nullptr || buffer->GetVirAddr() == nullptr) {
255 return false;
256 }
257 auto addr = static_cast<uint8_t *>(buffer->GetVirAddr());
258 if (!DoDraw(addr, buffer->GetWidth(), buffer->GetHeight(), imagePath)) {
259 WLOGE("draw window pixel failed");
260 return false;
261 }
262 OHOS::BufferFlushConfig flushConfig = {
263 .damage = {
264 .w = buffer->GetWidth(),
265 .h = buffer->GetHeight(),
266 },
267 };
268 OHOS::SurfaceError ret = layer->FlushBuffer(buffer, -1, flushConfig);
269 if (ret != OHOS::SurfaceError::SURFACE_ERROR_OK) {
270 WLOGFE("draw pointer FlushBuffer ret:%{public}s", SurfaceErrorStr(ret).c_str());
271 return false;
272 }
273 return true;
274 }
275
DrawImage(std::shared_ptr<RSSurfaceNode> surfaceNode,int32_t bufferWidth,int32_t bufferHeight,std::shared_ptr<Media::PixelMap> pixelMap)276 bool SurfaceDraw::DrawImage(std::shared_ptr<RSSurfaceNode> surfaceNode, int32_t bufferWidth,
277 int32_t bufferHeight, std::shared_ptr<Media::PixelMap> pixelMap)
278 {
279 sptr<OHOS::Surface> layer = GetLayer(surfaceNode);
280 if (layer == nullptr) {
281 WLOGFE("layer is nullptr");
282 return false;
283 }
284 sptr<OHOS::SurfaceBuffer> buffer = GetSurfaceBuffer(layer, bufferWidth, bufferHeight);
285 if (buffer == nullptr || buffer->GetVirAddr() == nullptr) {
286 return false;
287 }
288 auto addr = static_cast<uint8_t *>(buffer->GetVirAddr());
289 if (!DoDraw(addr, buffer->GetWidth(), buffer->GetHeight(), pixelMap)) {
290 WLOGE("draw window pixel failed");
291 return false;
292 }
293 OHOS::BufferFlushConfig flushConfig = {
294 .damage = {
295 .w = buffer->GetWidth(),
296 .h = buffer->GetHeight(),
297 },
298 };
299 OHOS::SurfaceError ret = layer->FlushBuffer(buffer, -1, flushConfig);
300 if (ret != OHOS::SurfaceError::SURFACE_ERROR_OK) {
301 WLOGFE("draw pointer FlushBuffer ret:%{public}s", SurfaceErrorStr(ret).c_str());
302 return false;
303 }
304 return true;
305 }
306
DrawColor(std::shared_ptr<RSSurfaceNode> surfaceNode,int32_t bufferWidth,int32_t bufferHeight,uint32_t color)307 bool SurfaceDraw::DrawColor(std::shared_ptr<RSSurfaceNode> surfaceNode, int32_t bufferWidth,
308 int32_t bufferHeight, uint32_t color)
309 {
310 sptr<OHOS::Surface> layer = GetLayer(surfaceNode);
311 if (layer == nullptr) {
312 WLOGFE("layer is nullptr");
313 return false;
314 }
315 sptr<OHOS::SurfaceBuffer> buffer = GetSurfaceBuffer(layer, bufferWidth, bufferHeight);
316 if (buffer == nullptr || buffer->GetVirAddr() == nullptr) {
317 return false;
318 }
319 auto addr = static_cast<uint8_t *>(buffer->GetVirAddr());
320 if (!DoDraw(addr, buffer->GetWidth(), buffer->GetHeight(), color)) {
321 WLOGE("draw window color failed");
322 return false;
323 }
324 OHOS::BufferFlushConfig flushConfig = {
325 .damage = {
326 .w = buffer->GetWidth(),
327 .h = buffer->GetHeight(),
328 },
329 };
330 OHOS::SurfaceError ret = layer->FlushBuffer(buffer, -1, flushConfig);
331 if (ret != OHOS::SurfaceError::SURFACE_ERROR_OK) {
332 WLOGFE("draw pointer FlushBuffer ret:%{public}s", SurfaceErrorStr(ret).c_str());
333 return false;
334 }
335 return true;
336 }
337
GetLayer(std::shared_ptr<RSSurfaceNode> surfaceNode)338 sptr<OHOS::Surface> SurfaceDraw::GetLayer(std::shared_ptr<RSSurfaceNode> surfaceNode)
339 {
340 if (surfaceNode == nullptr) {
341 return nullptr;
342 }
343 return surfaceNode->GetSurface();
344 }
345
GetSurfaceBuffer(sptr<OHOS::Surface> layer,int32_t bufferWidth,int32_t bufferHeight)346 sptr<OHOS::SurfaceBuffer> SurfaceDraw::GetSurfaceBuffer(sptr<OHOS::Surface> layer,
347 int32_t bufferWidth, int32_t bufferHeight)
348 {
349 sptr<OHOS::SurfaceBuffer> buffer;
350 int32_t releaseFence = 0;
351 OHOS::BufferRequestConfig config = {
352 .width = bufferWidth,
353 .height = bufferHeight,
354 .strideAlignment = 0x8,
355 .format = GRAPHIC_PIXEL_FMT_RGBA_8888,
356 .usage = BUFFER_USAGE_CPU_READ | BUFFER_USAGE_CPU_WRITE | BUFFER_USAGE_MEM_DMA,
357 };
358
359 OHOS::SurfaceError ret = layer->RequestBuffer(buffer, releaseFence, config);
360 if (ret != OHOS::SURFACE_ERROR_OK) {
361 WLOGFE("request buffer ret:%{public}s", SurfaceErrorStr(ret).c_str());
362 return nullptr;
363 }
364 return buffer;
365 }
366
DecodeImageToPixelMap(const std::string & imagePath)367 std::unique_ptr<OHOS::Media::PixelMap> SurfaceDraw::DecodeImageToPixelMap(const std::string& imagePath)
368 {
369 OHOS::Media::SourceOptions opts;
370 opts.formatHint = "image/png";
371 uint32_t ret = 0;
372 auto imageSource = OHOS::Media::ImageSource::CreateImageSource(imagePath, opts, ret);
373 if (imageSource == nullptr) {
374 WLOGFE("invalid image path.");
375 return nullptr;
376 }
377 std::set<std::string> formats;
378 ret = imageSource->GetSupportedFormats(formats);
379 WLOGFD("get supported format ret:%{public}u", ret);
380
381 OHOS::Media::DecodeOptions decodeOpts;
382 std::unique_ptr<OHOS::Media::PixelMap> pixelMap = imageSource->CreatePixelMap(decodeOpts, ret);
383 if (pixelMap == nullptr) {
384 WLOGFE("pixelMap is nullptr");
385 }
386 return pixelMap;
387 }
388
DrawPixelmap(Drawing::Canvas & canvas,const std::string & imagePath)389 void SurfaceDraw::DrawPixelmap(Drawing::Canvas& canvas, const std::string& imagePath)
390 {
391 std::unique_ptr<OHOS::Media::PixelMap> pixelmap = DecodeImageToPixelMap(imagePath);
392 if (pixelmap == nullptr) {
393 WLOGFE("drawing pixel map is nullptr");
394 return;
395 }
396 Drawing::Pen pen;
397 pen.SetAntiAlias(true);
398 pen.SetColor(Drawing::Color::COLOR_BLUE);
399 Drawing::scalar penWidth = 1;
400 pen.SetWidth(penWidth);
401 canvas.AttachPen(pen);
402 RSPixelMapUtil::DrawPixelMap(canvas, *pixelmap, 0, 0);
403 }
404
DoDraw(uint8_t * addr,uint32_t width,uint32_t height,const std::string & imagePath)405 bool SurfaceDraw::DoDraw(uint8_t* addr, uint32_t width, uint32_t height, const std::string& imagePath)
406 {
407 Drawing::Bitmap bitmap;
408 Drawing::BitmapFormat format { Drawing::ColorType::COLORTYPE_RGBA_8888,
409 Drawing::AlphaType::ALPHATYPE_OPAQUE };
410 bitmap.Build(width, height, format);
411 Drawing::Canvas canvas;
412 canvas.Bind(bitmap);
413 canvas.Clear(Drawing::Color::COLOR_TRANSPARENT);
414 DrawPixelmap(canvas, imagePath);
415 uint32_t addrSize = width * height * IMAGE_BYTES_STRIDE;
416 errno_t ret = memcpy_s(addr, addrSize, bitmap.GetPixels(), addrSize);
417 if (ret != EOK) {
418 WLOGFE("draw failed");
419 return false;
420 }
421 return true;
422 }
423
DoDraw(uint8_t * addr,uint32_t width,uint32_t height,std::shared_ptr<Media::PixelMap> pixelMap)424 bool SurfaceDraw::DoDraw(uint8_t* addr, uint32_t width, uint32_t height, std::shared_ptr<Media::PixelMap> pixelMap)
425 {
426 Drawing::Bitmap bitmap;
427 Drawing::Canvas canvas;
428 Drawing::BitmapFormat format { Drawing::ColorType::COLORTYPE_RGBA_8888, Drawing::AlphaType::ALPHATYPE_OPAQUE };
429 bitmap.Build(width, height, format);
430 canvas.Bind(bitmap);
431 canvas.Clear(Drawing::Color::COLOR_TRANSPARENT);
432
433 Drawing::Image image;
434 Drawing::Bitmap imageBitmap;
435 Drawing::SamplingOptions sampling = Drawing::SamplingOptions(Drawing::FilterMode::NEAREST,
436 Drawing::MipmapMode::NEAREST);
437 imageBitmap.Build(pixelMap->GetWidth(), pixelMap->GetHeight(), format);
438 imageBitmap.SetPixels(const_cast<uint8_t*>(pixelMap->GetPixels()));
439 image.BuildFromBitmap(imageBitmap);
440
441 Drawing::Rect dst(0, 0, width, height);
442 Drawing::Rect src(0, 0, pixelMap->GetWidth(), pixelMap->GetHeight());
443 canvas.DrawImageRect(image, src, dst, sampling);
444
445 uint32_t addrSize = width * height * IMAGE_BYTES_STRIDE;
446 errno_t ret = memcpy_s(addr, addrSize, bitmap.GetPixels(), addrSize);
447 if (ret != EOK) {
448 WLOGFE("draw failed");
449 return false;
450 }
451 return true;
452 }
453
DoDraw(uint8_t * addr,uint32_t width,uint32_t height,uint32_t color)454 bool SurfaceDraw::DoDraw(uint8_t* addr, uint32_t width, uint32_t height, uint32_t color)
455 {
456 Drawing::Bitmap bitmap;
457 Drawing::BitmapFormat format { Drawing::ColorType::COLORTYPE_RGBA_8888,
458 Drawing::AlphaType::ALPHATYPE_OPAQUE };
459 bitmap.Build(width, height, format);
460 Drawing::Canvas canvas;
461 canvas.Bind(bitmap);
462 canvas.Clear(color);
463
464 uint32_t addrSize = width * height * IMAGE_BYTES_STRIDE;
465 errno_t ret = memcpy_s(addr, addrSize, bitmap.GetPixels(), addrSize);
466 if (ret != EOK) {
467 WLOGFE("draw failed");
468 return false;
469 }
470 return true;
471 }
472
DrawImageRect(std::shared_ptr<RSSurfaceNode> surfaceNode,Rect rect,std::shared_ptr<Media::PixelMap> pixelMap,uint32_t color,bool fillWindow)473 bool SurfaceDraw::DrawImageRect(std::shared_ptr<RSSurfaceNode> surfaceNode, Rect rect,
474 std::shared_ptr<Media::PixelMap> pixelMap, uint32_t color, bool fillWindow)
475 {
476 int32_t winHeight = static_cast<int32_t>(rect.height_);
477 int32_t winWidth = static_cast<int32_t>(rect.width_);
478 sptr<OHOS::Surface> layer = GetLayer(surfaceNode);
479 if (layer == nullptr) {
480 WLOGFE("layer is nullptr");
481 return false;
482 }
483 sptr<OHOS::SurfaceBuffer> buffer = GetSurfaceBuffer(layer, winWidth, winHeight);
484 if (buffer == nullptr || buffer->GetVirAddr() == nullptr) {
485 return false;
486 }
487 if (!DoDrawImageRect(buffer, rect, pixelMap, color, fillWindow)) {
488 WLOGE("draw image rect failed.");
489 return false;
490 }
491 OHOS::BufferFlushConfig flushConfig = {
492 .damage = {
493 .w = buffer->GetWidth(),
494 .h = buffer->GetHeight(),
495 },
496 };
497 OHOS::SurfaceError surfaceRet = layer->FlushBuffer(buffer, -1, flushConfig);
498 if (surfaceRet != OHOS::SurfaceError::SURFACE_ERROR_OK) {
499 WLOGFE("draw pointer FlushBuffer ret:%{public}s", SurfaceErrorStr(surfaceRet).c_str());
500 return false;
501 }
502 return true;
503 }
504
DoDrawImageRect(sptr<OHOS::SurfaceBuffer> buffer,const Rect & rect,std::shared_ptr<Media::PixelMap> pixelMap,uint32_t color,bool fillWindow)505 bool SurfaceDraw::DoDrawImageRect(sptr<OHOS::SurfaceBuffer> buffer, const Rect& rect,
506 std::shared_ptr<Media::PixelMap> pixelMap, uint32_t color, bool fillWindow)
507 {
508 int32_t winWidth = static_cast<int32_t>(rect.width_);
509 int32_t winHeight = static_cast<int32_t>(rect.height_);
510 // actual width of the surface buffer after alignment
511 auto bufferStride = buffer->GetStride();
512 int32_t alignWidth = bufferStride / static_cast<int32_t>(IMAGE_BYTES_STRIDE);
513 if (pixelMap == nullptr) {
514 WLOGFE("drawing pixel map failed, because pixel map is nullptr.");
515 return false;
516 }
517 if (pixelMap->GetHeight() <= 0 || pixelMap->GetWidth() <= 0 || winWidth <= 0 || winHeight <= 0) {
518 WLOGFE("drawing pixel map failed, because width or height is invalid.");
519 return false;
520 }
521 Drawing::Bitmap bitmap;
522 Drawing::BitmapFormat format { Drawing::ColorType::COLORTYPE_RGBA_8888,
523 Drawing::AlphaType::ALPHATYPE_OPAQUE };
524 bitmap.Build(alignWidth, winHeight, format);
525 Drawing::Canvas canvas;
526 canvas.Bind(bitmap);
527 canvas.Clear(color);
528 float xAxis = static_cast<float>(winWidth) / pixelMap->GetWidth();
529 float yAxis = static_cast<float>(winHeight) / pixelMap->GetHeight();
530 float axis = std::min(xAxis, yAxis);
531 int scaledPixelMapW = pixelMap->GetWidth();
532 int scaledPixelMapH = pixelMap->GetHeight();
533 if (axis < 1.0) {
534 canvas.Scale(axis, axis);
535 scaledPixelMapW = scaledPixelMapW * axis;
536 scaledPixelMapH = scaledPixelMapH * axis;
537 } else if (fillWindow) {
538 // scale snapshot to whole window
539 canvas.Scale(xAxis, yAxis);
540 scaledPixelMapW = winWidth;
541 scaledPixelMapH = winHeight;
542 }
543 int left = (winWidth - scaledPixelMapW) / 2; // 2 is the left and right boundaries of the win
544 int top = (winHeight - scaledPixelMapH) / 2; // 2 is the top and bottom boundaries of the win
545 WLOGFD("pixelMap width: %{public}d win height: %{public}d left:%{public}d top:%{public}d.",
546 pixelMap->GetWidth(), pixelMap->GetHeight(), left, top);
547 RSPixelMapUtil::DrawPixelMap(canvas, *pixelMap, left, top);
548 // bufferSize is actual size of the surface buffer after alignment
549 int32_t bufferSize = bufferStride * winHeight;
550 uint8_t* bitmapAddr = static_cast<uint8_t*>(bitmap.GetPixels());
551 auto addr = static_cast<uint8_t *>(buffer->GetVirAddr());
552 errno_t ret = memcpy_s(addr, bufferSize, bitmapAddr, bufferSize);
553 if (ret != EOK) {
554 WLOGFE("draw image rect failed, because copy bitmap to buffer failed.");
555 return false;
556 }
557 return true;
558 }
559
GetSurfaceSnapshot(const std::shared_ptr<RSSurfaceNode> surfaceNode,std::shared_ptr<Media::PixelMap> & pixelMap,int32_t timeoutMs,float scaleW,float scaleH)560 bool SurfaceDraw::GetSurfaceSnapshot(const std::shared_ptr<RSSurfaceNode> surfaceNode,
561 std::shared_ptr<Media::PixelMap>&pixelMap, int32_t timeoutMs, float scaleW, float scaleH)
562 {
563 if (surfaceNode == nullptr) {
564 WLOGFE("surfaceNode is null");
565 return false;
566 }
567 HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "SurfaceDraw:GetSurfaceSnapshot(%llu)", surfaceNode->GetId());
568 std::shared_ptr<SurfaceCaptureFuture> callback = std::make_shared<SurfaceCaptureFuture>();
569 RSSurfaceCaptureConfig config = {
570 .scaleX = scaleW,
571 .scaleY = scaleH,
572 };
573 if (RSInterfaces::GetInstance().TakeSurfaceCapture(surfaceNode, callback, config)) {
574 pixelMap = callback->GetResult(timeoutMs); // get pixelmap time out ms
575 }
576 if (pixelMap == nullptr) {
577 WLOGE("get surface snapshot timeout.");
578 return false;
579 }
580 return true;
581 }
582
DrawMasking(std::shared_ptr<RSSurfaceNode> surfaceNode,Rect screenRect,Rect transparentRect)583 bool SurfaceDraw::DrawMasking(std::shared_ptr<RSSurfaceNode> surfaceNode, Rect screenRect,
584 Rect transparentRect)
585 {
586 int32_t screenHeight = static_cast<int32_t>(screenRect.height_);
587 int32_t screenWidth = static_cast<int32_t>(screenRect.width_);
588 int32_t transparentHeight = static_cast<int32_t>(transparentRect.height_);
589 int32_t transparentWidth = static_cast<int32_t>(transparentRect.width_);
590 sptr<OHOS::Surface> layer = GetLayer(surfaceNode);
591 if (layer == nullptr) {
592 WLOGFE("layer is nullptr");
593 return false;
594 }
595 sptr<OHOS::SurfaceBuffer> buffer = GetSurfaceBuffer(layer, screenWidth, screenHeight);
596 if (buffer == nullptr || buffer->GetVirAddr() == nullptr) {
597 return false;
598 }
599 auto addr = static_cast<uint8_t *>(buffer->GetVirAddr());
600 Drawing::Bitmap fullbitmap;
601 Drawing::BitmapFormat fullBitmapFormat { Drawing::ColorType::COLORTYPE_RGBA_8888,
602 Drawing::AlphaType::ALPHATYPE_OPAQUE };
603 fullbitmap.Build(screenWidth, screenHeight, fullBitmapFormat);
604 Drawing::Canvas canvas;
605 canvas.Bind(fullbitmap);
606 canvas.Clear(0xFF000000);
607 Drawing::Bitmap transBitmap;
608 Drawing::BitmapFormat transBitmapFormat { Drawing::ColorType::COLORTYPE_RGBA_8888,
609 Drawing::AlphaType::ALPHATYPE_OPAQUE };
610 transBitmap.Build(transparentWidth, transparentHeight, transBitmapFormat);
611 transBitmap.ClearWithColor(0);
612 canvas.DrawBitmap(transBitmap, static_cast<Drawing::scalar>(transparentRect.posX_),
613 static_cast<Drawing::scalar>(transparentRect.posY_));
614
615 uint32_t addrSize = static_cast<uint32_t>(screenWidth * screenHeight * IMAGE_BYTES_STRIDE);
616 errno_t ret = memcpy_s(addr, addrSize, fullbitmap.GetPixels(), addrSize);
617 if (ret != EOK) {
618 WLOGFE("draw failed");
619 return false;
620 }
621 OHOS::BufferFlushConfig flushConfig = {
622 .damage = {
623 .w = buffer->GetWidth(),
624 .h = buffer->GetHeight(),
625 },
626 };
627 OHOS::SurfaceError surfaceRet = layer->FlushBuffer(buffer, -1, flushConfig);
628 if (surfaceRet != OHOS::SurfaceError::SURFACE_ERROR_OK) {
629 WLOGFE("draw masking FlushBuffer ret:%{public}s", SurfaceErrorStr(surfaceRet).c_str());
630 return false;
631 }
632 return true;
633 }
634
DrawCustomStartingWindow(const std::shared_ptr<RSSurfaceNode> & surfaceNode,const Rect & rect,const std::shared_ptr<Rosen::StartingWindowPageDrawInfo> & info,float ratio,const std::array<uint32_t,size_t (StartWindowResType::Count)> & frameIndex)635 bool SurfaceDraw::DrawCustomStartingWindow(const std::shared_ptr<RSSurfaceNode>& surfaceNode,
636 const Rect& rect, const std::shared_ptr<Rosen::StartingWindowPageDrawInfo>& info,
637 float ratio, const std::array<uint32_t, size_t(StartWindowResType::Count)>& frameIndex)
638 {
639 int32_t winHeight = static_cast<int32_t>(rect.height_);
640 int32_t winWidth = static_cast<int32_t>(rect.width_);
641 sptr<OHOS::Surface> layer = GetLayer(surfaceNode);
642 if (layer == nullptr) {
643 TLOGD(WmsLogTag::WMS_PATTERN, "layer is nullptr");
644 return false;
645 }
646 sptr<OHOS::SurfaceBuffer> buffer = GetSurfaceBuffer(layer, winWidth, winHeight);
647 if (buffer == nullptr || buffer->GetVirAddr() == nullptr) {
648 TLOGD(WmsLogTag::WMS_PATTERN, "buffer or virAddr is nullptr");
649 return false;
650 }
651 if (!DoDrawCustomStartingWindow(buffer, rect, info, ratio, frameIndex)) {
652 TLOGD(WmsLogTag::WMS_PATTERN, "draw Custom startingwindow page failed");
653 return false;
654 }
655 OHOS::BufferFlushConfig flushConfig = {
656 .damage = {
657 .w = buffer->GetWidth(),
658 .h = buffer->GetHeight(),
659 },
660 };
661 OHOS::SurfaceError surfaceRet = layer->FlushBuffer(buffer, -1, flushConfig);
662 if (surfaceRet != OHOS::SurfaceError::SURFACE_ERROR_OK) {
663 TLOGD(WmsLogTag::WMS_PATTERN, "draw pointer FlushBuffer ret:%{public}s", SurfaceErrorStr(surfaceRet).c_str());
664 return false;
665 }
666 return true;
667 }
668
DoDrawCustomStartingWindow(const sptr<OHOS::SurfaceBuffer> & buffer,const Rect & rect,const std::shared_ptr<Rosen::StartingWindowPageDrawInfo> & info,const float ratio,const std::array<uint32_t,size_t (StartWindowResType::Count)> & frameIndex)669 bool SurfaceDraw::DoDrawCustomStartingWindow(const sptr<OHOS::SurfaceBuffer>& buffer, const Rect& rect,
670 const std::shared_ptr<Rosen::StartingWindowPageDrawInfo>& info, const float ratio,
671 const std::array<uint32_t, size_t(StartWindowResType::Count)>& frameIndex)
672 {
673 if (info == nullptr || rect.width_ <= 0 || rect.height_ <= 0 || ratio <= 0) {
674 TLOGD(WmsLogTag::WMS_PATTERN, "info is nullptr or invalid rect and ratio");
675 return false;
676 }
677 auto bufferStride = buffer->GetStride();
678 int32_t alignWidth = bufferStride / static_cast<int32_t>(IMAGE_BYTES_STRIDE);
679 Drawing::Bitmap customDrawBitmap;
680 Drawing::BitmapFormat format { Drawing::ColorType::COLORTYPE_RGBA_8888, Drawing::AlphaType::ALPHATYPE_OPAQUE };
681 customDrawBitmap.Build(alignWidth, rect.height_, format);
682 Drawing::Canvas canvas;
683 canvas.Bind(customDrawBitmap);
684 canvas.Clear(info->bgColor);
685 TryDrawResource(info->bgImage, frameIndex[(size_t)StartWindowResType::BgImage],
686 [&](const auto& map) { return DoDrawBackgroundImage(map, rect, canvas, info->startWindowBackgroundImageFit); },
687 "background image");
688
689 TryDrawResource(info->branding, frameIndex[(size_t)StartWindowResType::Branding],
690 [&](const auto& map) { return DoDrawBranding(map, rect, canvas, ratio, ImageFit::SCALE_DOWN); },
691 "branding image");
692
693 TryDrawResource(info->illustration, frameIndex[(size_t)StartWindowResType::Illustration],
694 [&](const auto& map) { return DoDrawIllustration(map, rect, canvas, ratio, ImageFit::SCALE_DOWN); },
695 "illustration image");
696
697 TryDrawResource(info->appIcon, frameIndex[(size_t)StartWindowResType::AppIcon],
698 [&](const auto& map) { return DoDrawAppIcon(map, rect, canvas, ratio, ImageFit::CONTAIN); },
699 "app icon image");
700 int32_t bufferSize = bufferStride * rect.height_;
701 uint8_t* bitmapAddr = static_cast<uint8_t*>(customDrawBitmap.GetPixels());
702 auto addr = static_cast<uint8_t *>(buffer->GetVirAddr());
703 errno_t ret = memcpy_s(addr, bufferSize, bitmapAddr, bufferSize);
704 if (ret != EOK) {
705 TLOGD(WmsLogTag::WMS_PATTERN, "draw image failed, because copy customDrawBitmap to buffer failed.");
706 return false;
707 }
708 return true;
709 }
710 } // Rosen
711 } // OHOS