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