1e0dac50fSopenharmony_ci/*
2e0dac50fSopenharmony_ci * Copyright (c) 2022 Huawei Device Co., Ltd.
3e0dac50fSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4e0dac50fSopenharmony_ci * you may not use this file except in compliance with the License.
5e0dac50fSopenharmony_ci * You may obtain a copy of the License at
6e0dac50fSopenharmony_ci *
7e0dac50fSopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
8e0dac50fSopenharmony_ci *
9e0dac50fSopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10e0dac50fSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11e0dac50fSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12e0dac50fSopenharmony_ci * See the License for the specific language governing permissions and
13e0dac50fSopenharmony_ci * limitations under the License.
14e0dac50fSopenharmony_ci */
15e0dac50fSopenharmony_ci
16e0dac50fSopenharmony_ci#include "surface_draw.h"
17e0dac50fSopenharmony_ci#include <algorithm>
18e0dac50fSopenharmony_ci#include <hitrace_meter.h>
19e0dac50fSopenharmony_ci#include <surface.h>
20e0dac50fSopenharmony_ci#include <transaction/rs_interfaces.h>
21e0dac50fSopenharmony_ci#include <ui/rs_surface_extractor.h>
22e0dac50fSopenharmony_ci
23e0dac50fSopenharmony_ci#include "image/bitmap.h"
24e0dac50fSopenharmony_ci#include "image_source.h"
25e0dac50fSopenharmony_ci#include "image_type.h"
26e0dac50fSopenharmony_ci#include "image_utils.h"
27e0dac50fSopenharmony_ci#include "render/rs_pixel_map_util.h"
28e0dac50fSopenharmony_ci#include "surface_capture_future.h"
29e0dac50fSopenharmony_ci#include "window_manager_hilog.h"
30e0dac50fSopenharmony_ci
31e0dac50fSopenharmony_cinamespace OHOS {
32e0dac50fSopenharmony_cinamespace Rosen {
33e0dac50fSopenharmony_cinamespace {
34e0dac50fSopenharmony_ciconstexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_WINDOW, "SurfaceDraw"};
35e0dac50fSopenharmony_ciconstexpr uint32_t IMAGE_BYTES_STRIDE = 4;
36e0dac50fSopenharmony_ci} // namespace
37e0dac50fSopenharmony_ci
38e0dac50fSopenharmony_cibool SurfaceDraw::DrawImage(std::shared_ptr<RSSurfaceNode> surfaceNode, int32_t bufferWidth,
39e0dac50fSopenharmony_ci    int32_t bufferHeight, const std::string& imagePath)
40e0dac50fSopenharmony_ci{
41e0dac50fSopenharmony_ci    sptr<OHOS::Surface> layer = GetLayer(surfaceNode);
42e0dac50fSopenharmony_ci    if (layer == nullptr) {
43e0dac50fSopenharmony_ci        WLOGFE("layer is nullptr");
44e0dac50fSopenharmony_ci        return false;
45e0dac50fSopenharmony_ci    }
46e0dac50fSopenharmony_ci    sptr<OHOS::SurfaceBuffer> buffer = GetSurfaceBuffer(layer, bufferWidth, bufferHeight);
47e0dac50fSopenharmony_ci    if (buffer == nullptr || buffer->GetVirAddr() == nullptr) {
48e0dac50fSopenharmony_ci        return false;
49e0dac50fSopenharmony_ci    }
50e0dac50fSopenharmony_ci    auto addr = static_cast<uint8_t *>(buffer->GetVirAddr());
51e0dac50fSopenharmony_ci    if (!DoDraw(addr, buffer->GetWidth(), buffer->GetHeight(), imagePath)) {
52e0dac50fSopenharmony_ci        WLOGE("draw window pixel failed");
53e0dac50fSopenharmony_ci        return false;
54e0dac50fSopenharmony_ci    }
55e0dac50fSopenharmony_ci    OHOS::BufferFlushConfig flushConfig = {
56e0dac50fSopenharmony_ci        .damage = {
57e0dac50fSopenharmony_ci            .w = buffer->GetWidth(),
58e0dac50fSopenharmony_ci            .h = buffer->GetHeight(),
59e0dac50fSopenharmony_ci        },
60e0dac50fSopenharmony_ci    };
61e0dac50fSopenharmony_ci    OHOS::SurfaceError ret = layer->FlushBuffer(buffer, -1, flushConfig);
62e0dac50fSopenharmony_ci    if (ret != OHOS::SurfaceError::SURFACE_ERROR_OK) {
63e0dac50fSopenharmony_ci        WLOGFE("draw pointer FlushBuffer ret:%{public}s", SurfaceErrorStr(ret).c_str());
64e0dac50fSopenharmony_ci        return false;
65e0dac50fSopenharmony_ci    }
66e0dac50fSopenharmony_ci    return true;
67e0dac50fSopenharmony_ci}
68e0dac50fSopenharmony_ci
69e0dac50fSopenharmony_cibool SurfaceDraw::DrawImage(std::shared_ptr<RSSurfaceNode> surfaceNode, int32_t bufferWidth,
70e0dac50fSopenharmony_ci    int32_t bufferHeight, std::shared_ptr<Media::PixelMap> pixelMap)
71e0dac50fSopenharmony_ci{
72e0dac50fSopenharmony_ci    sptr<OHOS::Surface> layer = GetLayer(surfaceNode);
73e0dac50fSopenharmony_ci    if (layer == nullptr) {
74e0dac50fSopenharmony_ci        WLOGFE("layer is nullptr");
75e0dac50fSopenharmony_ci        return false;
76e0dac50fSopenharmony_ci    }
77e0dac50fSopenharmony_ci    sptr<OHOS::SurfaceBuffer> buffer = GetSurfaceBuffer(layer, bufferWidth, bufferHeight);
78e0dac50fSopenharmony_ci    if (buffer == nullptr || buffer->GetVirAddr() == nullptr) {
79e0dac50fSopenharmony_ci        return false;
80e0dac50fSopenharmony_ci    }
81e0dac50fSopenharmony_ci    auto addr = static_cast<uint8_t *>(buffer->GetVirAddr());
82e0dac50fSopenharmony_ci    if (!DoDraw(addr, buffer->GetWidth(), buffer->GetHeight(), pixelMap)) {
83e0dac50fSopenharmony_ci        WLOGE("draw window pixel failed");
84e0dac50fSopenharmony_ci        return false;
85e0dac50fSopenharmony_ci    }
86e0dac50fSopenharmony_ci    OHOS::BufferFlushConfig flushConfig = {
87e0dac50fSopenharmony_ci        .damage = {
88e0dac50fSopenharmony_ci            .w = buffer->GetWidth(),
89e0dac50fSopenharmony_ci            .h = buffer->GetHeight(),
90e0dac50fSopenharmony_ci        },
91e0dac50fSopenharmony_ci    };
92e0dac50fSopenharmony_ci    OHOS::SurfaceError ret = layer->FlushBuffer(buffer, -1, flushConfig);
93e0dac50fSopenharmony_ci    if (ret != OHOS::SurfaceError::SURFACE_ERROR_OK) {
94e0dac50fSopenharmony_ci        WLOGFE("draw pointer FlushBuffer ret:%{public}s", SurfaceErrorStr(ret).c_str());
95e0dac50fSopenharmony_ci        return false;
96e0dac50fSopenharmony_ci    }
97e0dac50fSopenharmony_ci    return true;
98e0dac50fSopenharmony_ci}
99e0dac50fSopenharmony_ci
100e0dac50fSopenharmony_cibool SurfaceDraw::DrawColor(std::shared_ptr<RSSurfaceNode> surfaceNode, int32_t bufferWidth,
101e0dac50fSopenharmony_ci    int32_t bufferHeight, uint32_t color)
102e0dac50fSopenharmony_ci{
103e0dac50fSopenharmony_ci    sptr<OHOS::Surface> layer = GetLayer(surfaceNode);
104e0dac50fSopenharmony_ci    if (layer == nullptr) {
105e0dac50fSopenharmony_ci        WLOGFE("layer is nullptr");
106e0dac50fSopenharmony_ci        return false;
107e0dac50fSopenharmony_ci    }
108e0dac50fSopenharmony_ci    sptr<OHOS::SurfaceBuffer> buffer = GetSurfaceBuffer(layer, bufferWidth, bufferHeight);
109e0dac50fSopenharmony_ci    if (buffer == nullptr || buffer->GetVirAddr() == nullptr) {
110e0dac50fSopenharmony_ci        return false;
111e0dac50fSopenharmony_ci    }
112e0dac50fSopenharmony_ci    auto addr = static_cast<uint8_t *>(buffer->GetVirAddr());
113e0dac50fSopenharmony_ci    if (!DoDraw(addr, buffer->GetWidth(), buffer->GetHeight(), color)) {
114e0dac50fSopenharmony_ci        WLOGE("draw window color failed");
115e0dac50fSopenharmony_ci        return false;
116e0dac50fSopenharmony_ci    }
117e0dac50fSopenharmony_ci    OHOS::BufferFlushConfig flushConfig = {
118e0dac50fSopenharmony_ci        .damage = {
119e0dac50fSopenharmony_ci            .w = buffer->GetWidth(),
120e0dac50fSopenharmony_ci            .h = buffer->GetHeight(),
121e0dac50fSopenharmony_ci        },
122e0dac50fSopenharmony_ci    };
123e0dac50fSopenharmony_ci    OHOS::SurfaceError ret = layer->FlushBuffer(buffer, -1, flushConfig);
124e0dac50fSopenharmony_ci    if (ret != OHOS::SurfaceError::SURFACE_ERROR_OK) {
125e0dac50fSopenharmony_ci        WLOGFE("draw pointer FlushBuffer ret:%{public}s", SurfaceErrorStr(ret).c_str());
126e0dac50fSopenharmony_ci        return false;
127e0dac50fSopenharmony_ci    }
128e0dac50fSopenharmony_ci    return true;
129e0dac50fSopenharmony_ci}
130e0dac50fSopenharmony_ci
131e0dac50fSopenharmony_cisptr<OHOS::Surface> SurfaceDraw::GetLayer(std::shared_ptr<RSSurfaceNode> surfaceNode)
132e0dac50fSopenharmony_ci{
133e0dac50fSopenharmony_ci    if (surfaceNode == nullptr) {
134e0dac50fSopenharmony_ci        return nullptr;
135e0dac50fSopenharmony_ci    }
136e0dac50fSopenharmony_ci    return surfaceNode->GetSurface();
137e0dac50fSopenharmony_ci}
138e0dac50fSopenharmony_ci
139e0dac50fSopenharmony_cisptr<OHOS::SurfaceBuffer> SurfaceDraw::GetSurfaceBuffer(sptr<OHOS::Surface> layer,
140e0dac50fSopenharmony_ci    int32_t bufferWidth, int32_t bufferHeight)
141e0dac50fSopenharmony_ci{
142e0dac50fSopenharmony_ci    sptr<OHOS::SurfaceBuffer> buffer;
143e0dac50fSopenharmony_ci    int32_t releaseFence = 0;
144e0dac50fSopenharmony_ci    OHOS::BufferRequestConfig config = {
145e0dac50fSopenharmony_ci        .width = bufferWidth,
146e0dac50fSopenharmony_ci        .height = bufferHeight,
147e0dac50fSopenharmony_ci        .strideAlignment = 0x8,
148e0dac50fSopenharmony_ci        .format = GRAPHIC_PIXEL_FMT_RGBA_8888,
149e0dac50fSopenharmony_ci        .usage = BUFFER_USAGE_CPU_READ | BUFFER_USAGE_CPU_WRITE | BUFFER_USAGE_MEM_DMA,
150e0dac50fSopenharmony_ci    };
151e0dac50fSopenharmony_ci
152e0dac50fSopenharmony_ci    OHOS::SurfaceError ret = layer->RequestBuffer(buffer, releaseFence, config);
153e0dac50fSopenharmony_ci    if (ret != OHOS::SURFACE_ERROR_OK) {
154e0dac50fSopenharmony_ci        WLOGFE("request buffer ret:%{public}s", SurfaceErrorStr(ret).c_str());
155e0dac50fSopenharmony_ci        return nullptr;
156e0dac50fSopenharmony_ci    }
157e0dac50fSopenharmony_ci    return buffer;
158e0dac50fSopenharmony_ci}
159e0dac50fSopenharmony_ci
160e0dac50fSopenharmony_cistd::unique_ptr<OHOS::Media::PixelMap> SurfaceDraw::DecodeImageToPixelMap(const std::string& imagePath)
161e0dac50fSopenharmony_ci{
162e0dac50fSopenharmony_ci    OHOS::Media::SourceOptions opts;
163e0dac50fSopenharmony_ci    opts.formatHint = "image/png";
164e0dac50fSopenharmony_ci    uint32_t ret = 0;
165e0dac50fSopenharmony_ci    auto imageSource = OHOS::Media::ImageSource::CreateImageSource(imagePath, opts, ret);
166e0dac50fSopenharmony_ci    if (imageSource == nullptr) {
167e0dac50fSopenharmony_ci        WLOGFE("invalid image path.");
168e0dac50fSopenharmony_ci        return nullptr;
169e0dac50fSopenharmony_ci    }
170e0dac50fSopenharmony_ci    std::set<std::string> formats;
171e0dac50fSopenharmony_ci    ret = imageSource->GetSupportedFormats(formats);
172e0dac50fSopenharmony_ci    WLOGFD("get supported format ret:%{public}u", ret);
173e0dac50fSopenharmony_ci
174e0dac50fSopenharmony_ci    OHOS::Media::DecodeOptions decodeOpts;
175e0dac50fSopenharmony_ci    std::unique_ptr<OHOS::Media::PixelMap> pixelMap = imageSource->CreatePixelMap(decodeOpts, ret);
176e0dac50fSopenharmony_ci    if (pixelMap == nullptr) {
177e0dac50fSopenharmony_ci        WLOGFE("pixelMap is nullptr");
178e0dac50fSopenharmony_ci    }
179e0dac50fSopenharmony_ci    return pixelMap;
180e0dac50fSopenharmony_ci}
181e0dac50fSopenharmony_ci
182e0dac50fSopenharmony_civoid SurfaceDraw::DrawPixelmap(Drawing::Canvas& canvas, const std::string& imagePath)
183e0dac50fSopenharmony_ci{
184e0dac50fSopenharmony_ci    std::unique_ptr<OHOS::Media::PixelMap> pixelmap = DecodeImageToPixelMap(imagePath);
185e0dac50fSopenharmony_ci    if (pixelmap == nullptr) {
186e0dac50fSopenharmony_ci        WLOGFE("drawing pixel map is nullptr");
187e0dac50fSopenharmony_ci        return;
188e0dac50fSopenharmony_ci    }
189e0dac50fSopenharmony_ci    Drawing::Pen pen;
190e0dac50fSopenharmony_ci    pen.SetAntiAlias(true);
191e0dac50fSopenharmony_ci    pen.SetColor(Drawing::Color::COLOR_BLUE);
192e0dac50fSopenharmony_ci    Drawing::scalar penWidth = 1;
193e0dac50fSopenharmony_ci    pen.SetWidth(penWidth);
194e0dac50fSopenharmony_ci    canvas.AttachPen(pen);
195e0dac50fSopenharmony_ci    RSPixelMapUtil::DrawPixelMap(canvas, *pixelmap, 0, 0);
196e0dac50fSopenharmony_ci}
197e0dac50fSopenharmony_ci
198e0dac50fSopenharmony_cibool SurfaceDraw::DoDraw(uint8_t* addr, uint32_t width, uint32_t height, const std::string& imagePath)
199e0dac50fSopenharmony_ci{
200e0dac50fSopenharmony_ci    Drawing::Bitmap bitmap;
201e0dac50fSopenharmony_ci    Drawing::BitmapFormat format { Drawing::ColorType::COLORTYPE_RGBA_8888,
202e0dac50fSopenharmony_ci        Drawing::AlphaType::ALPHATYPE_OPAQUE };
203e0dac50fSopenharmony_ci    bitmap.Build(width, height, format);
204e0dac50fSopenharmony_ci    Drawing::Canvas canvas;
205e0dac50fSopenharmony_ci    canvas.Bind(bitmap);
206e0dac50fSopenharmony_ci    canvas.Clear(Drawing::Color::COLOR_TRANSPARENT);
207e0dac50fSopenharmony_ci    DrawPixelmap(canvas, imagePath);
208e0dac50fSopenharmony_ci    uint32_t addrSize = width * height * IMAGE_BYTES_STRIDE;
209e0dac50fSopenharmony_ci    errno_t ret = memcpy_s(addr, addrSize, bitmap.GetPixels(), addrSize);
210e0dac50fSopenharmony_ci    if (ret != EOK) {
211e0dac50fSopenharmony_ci        WLOGFE("draw failed");
212e0dac50fSopenharmony_ci        return false;
213e0dac50fSopenharmony_ci    }
214e0dac50fSopenharmony_ci    return true;
215e0dac50fSopenharmony_ci}
216e0dac50fSopenharmony_ci
217e0dac50fSopenharmony_cibool SurfaceDraw::DoDraw(uint8_t* addr, uint32_t width, uint32_t height, std::shared_ptr<Media::PixelMap> pixelMap)
218e0dac50fSopenharmony_ci{
219e0dac50fSopenharmony_ci    Drawing::Bitmap bitmap;
220e0dac50fSopenharmony_ci    Drawing::Canvas canvas;
221e0dac50fSopenharmony_ci    Drawing::BitmapFormat format { Drawing::ColorType::COLORTYPE_RGBA_8888, Drawing::AlphaType::ALPHATYPE_OPAQUE };
222e0dac50fSopenharmony_ci    bitmap.Build(width, height, format);
223e0dac50fSopenharmony_ci    canvas.Bind(bitmap);
224e0dac50fSopenharmony_ci    canvas.Clear(Drawing::Color::COLOR_TRANSPARENT);
225e0dac50fSopenharmony_ci
226e0dac50fSopenharmony_ci    Drawing::Image image;
227e0dac50fSopenharmony_ci    Drawing::Bitmap imageBitmap;
228e0dac50fSopenharmony_ci    Drawing::SamplingOptions sampling = Drawing::SamplingOptions(Drawing::FilterMode::NEAREST,
229e0dac50fSopenharmony_ci        Drawing::MipmapMode::NEAREST);
230e0dac50fSopenharmony_ci    imageBitmap.Build(pixelMap->GetWidth(), pixelMap->GetHeight(), format);
231e0dac50fSopenharmony_ci    imageBitmap.SetPixels(const_cast<uint8_t*>(pixelMap->GetPixels()));
232e0dac50fSopenharmony_ci    image.BuildFromBitmap(imageBitmap);
233e0dac50fSopenharmony_ci
234e0dac50fSopenharmony_ci    Drawing::Rect dst(0, 0, width, height);
235e0dac50fSopenharmony_ci    Drawing::Rect src(0, 0, pixelMap->GetWidth(), pixelMap->GetHeight());
236e0dac50fSopenharmony_ci    canvas.DrawImageRect(image, src, dst, sampling);
237e0dac50fSopenharmony_ci
238e0dac50fSopenharmony_ci    uint32_t addrSize = width * height * IMAGE_BYTES_STRIDE;
239e0dac50fSopenharmony_ci    errno_t ret = memcpy_s(addr, addrSize, bitmap.GetPixels(), addrSize);
240e0dac50fSopenharmony_ci    if (ret != EOK) {
241e0dac50fSopenharmony_ci        WLOGFE("draw failed");
242e0dac50fSopenharmony_ci        return false;
243e0dac50fSopenharmony_ci    }
244e0dac50fSopenharmony_ci    return true;
245e0dac50fSopenharmony_ci}
246e0dac50fSopenharmony_ci
247e0dac50fSopenharmony_cibool SurfaceDraw::DoDraw(uint8_t* addr, uint32_t width, uint32_t height, uint32_t color)
248e0dac50fSopenharmony_ci{
249e0dac50fSopenharmony_ci    Drawing::Bitmap bitmap;
250e0dac50fSopenharmony_ci    Drawing::BitmapFormat format { Drawing::ColorType::COLORTYPE_RGBA_8888,
251e0dac50fSopenharmony_ci        Drawing::AlphaType::ALPHATYPE_OPAQUE };
252e0dac50fSopenharmony_ci    bitmap.Build(width, height, format);
253e0dac50fSopenharmony_ci    Drawing::Canvas canvas;
254e0dac50fSopenharmony_ci    canvas.Bind(bitmap);
255e0dac50fSopenharmony_ci    canvas.Clear(color);
256e0dac50fSopenharmony_ci
257e0dac50fSopenharmony_ci    uint32_t addrSize = width * height * IMAGE_BYTES_STRIDE;
258e0dac50fSopenharmony_ci    errno_t ret = memcpy_s(addr, addrSize, bitmap.GetPixels(), addrSize);
259e0dac50fSopenharmony_ci    if (ret != EOK) {
260e0dac50fSopenharmony_ci        WLOGFE("draw failed");
261e0dac50fSopenharmony_ci        return false;
262e0dac50fSopenharmony_ci    }
263e0dac50fSopenharmony_ci    return true;
264e0dac50fSopenharmony_ci}
265e0dac50fSopenharmony_ci
266e0dac50fSopenharmony_cibool SurfaceDraw::DrawImageRect(std::shared_ptr<RSSurfaceNode> surfaceNode, Rect rect,
267e0dac50fSopenharmony_ci    std::shared_ptr<Media::PixelMap> pixelMap, uint32_t color, bool fillWindow)
268e0dac50fSopenharmony_ci{
269e0dac50fSopenharmony_ci    int32_t winHeight = static_cast<int32_t>(rect.height_);
270e0dac50fSopenharmony_ci    int32_t winWidth = static_cast<int32_t>(rect.width_);
271e0dac50fSopenharmony_ci    sptr<OHOS::Surface> layer = GetLayer(surfaceNode);
272e0dac50fSopenharmony_ci    if (layer == nullptr) {
273e0dac50fSopenharmony_ci        WLOGFE("layer is nullptr");
274e0dac50fSopenharmony_ci        return false;
275e0dac50fSopenharmony_ci    }
276e0dac50fSopenharmony_ci    sptr<OHOS::SurfaceBuffer> buffer = GetSurfaceBuffer(layer, winWidth, winHeight);
277e0dac50fSopenharmony_ci    if (buffer == nullptr || buffer->GetVirAddr() == nullptr) {
278e0dac50fSopenharmony_ci        return false;
279e0dac50fSopenharmony_ci    }
280e0dac50fSopenharmony_ci    if (!DoDrawImageRect(buffer, rect, pixelMap, color, fillWindow)) {
281e0dac50fSopenharmony_ci        WLOGE("draw image rect failed.");
282e0dac50fSopenharmony_ci        return false;
283e0dac50fSopenharmony_ci    }
284e0dac50fSopenharmony_ci    OHOS::BufferFlushConfig flushConfig = {
285e0dac50fSopenharmony_ci        .damage = {
286e0dac50fSopenharmony_ci            .w = buffer->GetWidth(),
287e0dac50fSopenharmony_ci            .h = buffer->GetHeight(),
288e0dac50fSopenharmony_ci        },
289e0dac50fSopenharmony_ci    };
290e0dac50fSopenharmony_ci    OHOS::SurfaceError surfaceRet = layer->FlushBuffer(buffer, -1, flushConfig);
291e0dac50fSopenharmony_ci    if (surfaceRet != OHOS::SurfaceError::SURFACE_ERROR_OK) {
292e0dac50fSopenharmony_ci        WLOGFE("draw pointer FlushBuffer ret:%{public}s", SurfaceErrorStr(surfaceRet).c_str());
293e0dac50fSopenharmony_ci        return false;
294e0dac50fSopenharmony_ci    }
295e0dac50fSopenharmony_ci    return true;
296e0dac50fSopenharmony_ci}
297e0dac50fSopenharmony_ci
298e0dac50fSopenharmony_cibool SurfaceDraw::DoDrawImageRect(sptr<OHOS::SurfaceBuffer> buffer, const Rect& rect,
299e0dac50fSopenharmony_ci    std::shared_ptr<Media::PixelMap> pixelMap, uint32_t color, bool fillWindow)
300e0dac50fSopenharmony_ci{
301e0dac50fSopenharmony_ci    int32_t winWidth = static_cast<int32_t>(rect.width_);
302e0dac50fSopenharmony_ci    int32_t winHeight = static_cast<int32_t>(rect.height_);
303e0dac50fSopenharmony_ci    // actual width of the surface buffer after alignment
304e0dac50fSopenharmony_ci    auto bufferStride = buffer->GetStride();
305e0dac50fSopenharmony_ci    int32_t alignWidth = bufferStride / static_cast<int32_t>(IMAGE_BYTES_STRIDE);
306e0dac50fSopenharmony_ci    if (pixelMap == nullptr) {
307e0dac50fSopenharmony_ci        WLOGFE("drawing pixel map failed, because pixel map is nullptr.");
308e0dac50fSopenharmony_ci        return false;
309e0dac50fSopenharmony_ci    }
310e0dac50fSopenharmony_ci    if (pixelMap->GetHeight() <= 0 || pixelMap->GetWidth() <= 0 || winWidth <= 0 || winHeight <= 0) {
311e0dac50fSopenharmony_ci        WLOGFE("drawing pixel map failed, because width or height is invalid.");
312e0dac50fSopenharmony_ci        return false;
313e0dac50fSopenharmony_ci    }
314e0dac50fSopenharmony_ci    Drawing::Bitmap bitmap;
315e0dac50fSopenharmony_ci    Drawing::BitmapFormat format { Drawing::ColorType::COLORTYPE_RGBA_8888,
316e0dac50fSopenharmony_ci        Drawing::AlphaType::ALPHATYPE_OPAQUE };
317e0dac50fSopenharmony_ci    bitmap.Build(alignWidth, winHeight, format);
318e0dac50fSopenharmony_ci    Drawing::Canvas canvas;
319e0dac50fSopenharmony_ci    canvas.Bind(bitmap);
320e0dac50fSopenharmony_ci    canvas.Clear(color);
321e0dac50fSopenharmony_ci    float xAxis = static_cast<float>(winWidth) / pixelMap->GetWidth();
322e0dac50fSopenharmony_ci    float yAxis = static_cast<float>(winHeight) / pixelMap->GetHeight();
323e0dac50fSopenharmony_ci    float axis = std::min(xAxis, yAxis);
324e0dac50fSopenharmony_ci    int scaledPixelMapW = pixelMap->GetWidth();
325e0dac50fSopenharmony_ci    int scaledPixelMapH = pixelMap->GetHeight();
326e0dac50fSopenharmony_ci    if (axis < 1.0) {
327e0dac50fSopenharmony_ci        canvas.Scale(axis, axis);
328e0dac50fSopenharmony_ci        scaledPixelMapW = scaledPixelMapW * axis;
329e0dac50fSopenharmony_ci        scaledPixelMapH = scaledPixelMapH * axis;
330e0dac50fSopenharmony_ci    } else if (fillWindow) {
331e0dac50fSopenharmony_ci        // scale snapshot to whole window
332e0dac50fSopenharmony_ci        canvas.Scale(xAxis, yAxis);
333e0dac50fSopenharmony_ci        scaledPixelMapW = winWidth;
334e0dac50fSopenharmony_ci        scaledPixelMapH = winHeight;
335e0dac50fSopenharmony_ci    }
336e0dac50fSopenharmony_ci    int left = (winWidth - scaledPixelMapW) / 2; // 2 is the left and right boundaries of the win
337e0dac50fSopenharmony_ci    int top = (winHeight - scaledPixelMapH) / 2; // 2 is the top and bottom boundaries of the win
338e0dac50fSopenharmony_ci    WLOGFD("pixelMap width: %{public}d win height: %{public}d left:%{public}d top:%{public}d.",
339e0dac50fSopenharmony_ci        pixelMap->GetWidth(), pixelMap->GetHeight(), left, top);
340e0dac50fSopenharmony_ci    RSPixelMapUtil::DrawPixelMap(canvas, *pixelMap, left, top);
341e0dac50fSopenharmony_ci    // bufferSize is actual size of the surface buffer after alignment
342e0dac50fSopenharmony_ci    int32_t bufferSize = bufferStride * winHeight;
343e0dac50fSopenharmony_ci    uint8_t* bitmapAddr = static_cast<uint8_t*>(bitmap.GetPixels());
344e0dac50fSopenharmony_ci    auto addr = static_cast<uint8_t *>(buffer->GetVirAddr());
345e0dac50fSopenharmony_ci    errno_t ret = memcpy_s(addr, bufferSize, bitmapAddr, bufferSize);
346e0dac50fSopenharmony_ci    if (ret != EOK) {
347e0dac50fSopenharmony_ci        WLOGFE("draw image rect failed, because copy bitmap to buffer failed.");
348e0dac50fSopenharmony_ci        return false;
349e0dac50fSopenharmony_ci    }
350e0dac50fSopenharmony_ci    return true;
351e0dac50fSopenharmony_ci}
352e0dac50fSopenharmony_ci
353e0dac50fSopenharmony_cibool SurfaceDraw::GetSurfaceSnapshot(const std::shared_ptr<RSSurfaceNode> surfaceNode,
354e0dac50fSopenharmony_ci    std::shared_ptr<Media::PixelMap>&pixelMap, int32_t timeoutMs, float scaleW, float scaleH)
355e0dac50fSopenharmony_ci{
356e0dac50fSopenharmony_ci    if (surfaceNode == nullptr) {
357e0dac50fSopenharmony_ci        WLOGFE("surfaceNode is null");
358e0dac50fSopenharmony_ci        return false;
359e0dac50fSopenharmony_ci    }
360e0dac50fSopenharmony_ci    HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "SurfaceDraw:GetSurfaceSnapshot(%llu)", surfaceNode->GetId());
361e0dac50fSopenharmony_ci    std::shared_ptr<SurfaceCaptureFuture> callback = std::make_shared<SurfaceCaptureFuture>();
362e0dac50fSopenharmony_ci    RSSurfaceCaptureConfig config = {
363e0dac50fSopenharmony_ci        .scaleX = scaleW,
364e0dac50fSopenharmony_ci        .scaleY = scaleH,
365e0dac50fSopenharmony_ci    };
366e0dac50fSopenharmony_ci    if (RSInterfaces::GetInstance().TakeSurfaceCapture(surfaceNode, callback, config)) {
367e0dac50fSopenharmony_ci        pixelMap = callback->GetResult(timeoutMs); // get pixelmap time out ms
368e0dac50fSopenharmony_ci    }
369e0dac50fSopenharmony_ci    if (pixelMap == nullptr) {
370e0dac50fSopenharmony_ci        WLOGE("get surface snapshot timeout.");
371e0dac50fSopenharmony_ci        return false;
372e0dac50fSopenharmony_ci    }
373e0dac50fSopenharmony_ci    return true;
374e0dac50fSopenharmony_ci}
375e0dac50fSopenharmony_ci
376e0dac50fSopenharmony_cibool SurfaceDraw::DrawMasking(std::shared_ptr<RSSurfaceNode> surfaceNode, Rect screenRect,
377e0dac50fSopenharmony_ci    Rect transparentRect)
378e0dac50fSopenharmony_ci{
379e0dac50fSopenharmony_ci    int32_t screenHeight = static_cast<int32_t>(screenRect.height_);
380e0dac50fSopenharmony_ci    int32_t screenWidth = static_cast<int32_t>(screenRect.width_);
381e0dac50fSopenharmony_ci    int32_t transparentHeight = static_cast<int32_t>(transparentRect.height_);
382e0dac50fSopenharmony_ci    int32_t transparentWidth = static_cast<int32_t>(transparentRect.width_);
383e0dac50fSopenharmony_ci    sptr<OHOS::Surface> layer = GetLayer(surfaceNode);
384e0dac50fSopenharmony_ci    if (layer == nullptr) {
385e0dac50fSopenharmony_ci        WLOGFE("layer is nullptr");
386e0dac50fSopenharmony_ci        return false;
387e0dac50fSopenharmony_ci    }
388e0dac50fSopenharmony_ci    sptr<OHOS::SurfaceBuffer> buffer = GetSurfaceBuffer(layer, screenWidth, screenHeight);
389e0dac50fSopenharmony_ci    if (buffer == nullptr || buffer->GetVirAddr() == nullptr) {
390e0dac50fSopenharmony_ci        return false;
391e0dac50fSopenharmony_ci    }
392e0dac50fSopenharmony_ci    auto addr = static_cast<uint8_t *>(buffer->GetVirAddr());
393e0dac50fSopenharmony_ci    Drawing::Bitmap fullbitmap;
394e0dac50fSopenharmony_ci    Drawing::BitmapFormat fullBitmapFormat { Drawing::ColorType::COLORTYPE_RGBA_8888,
395e0dac50fSopenharmony_ci        Drawing::AlphaType::ALPHATYPE_OPAQUE };
396e0dac50fSopenharmony_ci    fullbitmap.Build(screenWidth, screenHeight, fullBitmapFormat);
397e0dac50fSopenharmony_ci    Drawing::Canvas canvas;
398e0dac50fSopenharmony_ci    canvas.Bind(fullbitmap);
399e0dac50fSopenharmony_ci    canvas.Clear(0xFF000000);
400e0dac50fSopenharmony_ci    Drawing::Bitmap transBitmap;
401e0dac50fSopenharmony_ci    Drawing::BitmapFormat transBitmapFormat { Drawing::ColorType::COLORTYPE_RGBA_8888,
402e0dac50fSopenharmony_ci        Drawing::AlphaType::ALPHATYPE_OPAQUE };
403e0dac50fSopenharmony_ci    transBitmap.Build(transparentWidth, transparentHeight, transBitmapFormat);
404e0dac50fSopenharmony_ci    transBitmap.ClearWithColor(0);
405e0dac50fSopenharmony_ci    canvas.DrawBitmap(transBitmap, static_cast<Drawing::scalar>(transparentRect.posX_),
406e0dac50fSopenharmony_ci        static_cast<Drawing::scalar>(transparentRect.posY_));
407e0dac50fSopenharmony_ci
408e0dac50fSopenharmony_ci    uint32_t addrSize = static_cast<uint32_t>(screenWidth * screenHeight * IMAGE_BYTES_STRIDE);
409e0dac50fSopenharmony_ci    errno_t ret = memcpy_s(addr, addrSize, fullbitmap.GetPixels(), addrSize);
410e0dac50fSopenharmony_ci    if (ret != EOK) {
411e0dac50fSopenharmony_ci        WLOGFE("draw failed");
412e0dac50fSopenharmony_ci        return false;
413e0dac50fSopenharmony_ci    }
414e0dac50fSopenharmony_ci    OHOS::BufferFlushConfig flushConfig = {
415e0dac50fSopenharmony_ci        .damage = {
416e0dac50fSopenharmony_ci            .w = buffer->GetWidth(),
417e0dac50fSopenharmony_ci            .h = buffer->GetHeight(),
418e0dac50fSopenharmony_ci        },
419e0dac50fSopenharmony_ci    };
420e0dac50fSopenharmony_ci    OHOS::SurfaceError surfaceRet = layer->FlushBuffer(buffer, -1, flushConfig);
421e0dac50fSopenharmony_ci    if (surfaceRet != OHOS::SurfaceError::SURFACE_ERROR_OK) {
422e0dac50fSopenharmony_ci        WLOGFE("draw masking FlushBuffer ret:%{public}s", SurfaceErrorStr(surfaceRet).c_str());
423e0dac50fSopenharmony_ci        return false;
424e0dac50fSopenharmony_ci    }
425e0dac50fSopenharmony_ci    return true;
426e0dac50fSopenharmony_ci}
427e0dac50fSopenharmony_ci} // Rosen
428e0dac50fSopenharmony_ci} // OHOS