Files
windowmanager/utils/src/surface_draw.cpp
T
xingyanan 2514e65484 Merge branch 'master' of https://gitee.com/openharmony/windowmanager into split_start_dev
Change-Id: Iae830e427028ce62c4c74ca41ea0ec921d22e22d
Signed-off-by: xingyanan <xingyanan2@huawei.com>
2022-07-04 15:48:42 +08:00

278 lines
9.7 KiB
C++

/*
* Copyright (c) 2022-2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "surface_draw.h"
#include <algorithm>
#include <surface.h>
#include <ui/rs_surface_extractor.h>
#include "window_manager_hilog.h"
#include "image/bitmap.h"
#include "image_source.h"
#include "image_type.h"
#include "image_utils.h"
#include "pixel_map.h"
namespace OHOS {
namespace Rosen {
namespace {
constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_WINDOW, "SurfaceDraw"};
} // namespace
bool SurfaceDraw::DrawImage(std::shared_ptr<OHOS::Rosen::RSSurfaceNode> surfaceNode, int32_t bufferWidth,
int32_t bufferHeight, const std::string& imagePath)
{
sptr<OHOS::Surface> layer = GetLayer(surfaceNode);
if (layer == nullptr) {
WLOGFE("layer is nullptr");
return false;
}
sptr<OHOS::SurfaceBuffer> buffer = GetSurfaceBuffer(layer, bufferWidth, bufferHeight);
if (buffer == nullptr || buffer->GetVirAddr() == nullptr) {
return false;
}
auto addr = static_cast<uint8_t *>(buffer->GetVirAddr());
if (!DoDraw(addr, buffer->GetWidth(), buffer->GetHeight(), imagePath)) {
WLOGE("draw window pixel failed");
return false;
}
OHOS::BufferFlushConfig flushConfig = {
.damage = {
.w = buffer->GetWidth(),
.h = buffer->GetHeight(),
},
};
OHOS::SurfaceError ret = layer->FlushBuffer(buffer, -1, flushConfig);
if (ret != OHOS::SurfaceError::SURFACE_ERROR_OK) {
WLOGFE("draw pointer FlushBuffer ret:%{public}s", SurfaceErrorStr(ret).c_str());
return false;
}
return true;
}
bool SurfaceDraw::DrawColor(std::shared_ptr<OHOS::Rosen::RSSurfaceNode> surfaceNode, int32_t bufferWidth,
int32_t bufferHeight, uint32_t color)
{
sptr<OHOS::Surface> layer = GetLayer(surfaceNode);
if (layer == nullptr) {
WLOGFE("layer is nullptr");
return false;
}
sptr<OHOS::SurfaceBuffer> buffer = GetSurfaceBuffer(layer, bufferWidth, bufferHeight);
if (buffer == nullptr || buffer->GetVirAddr() == nullptr) {
return false;
}
auto addr = static_cast<uint8_t *>(buffer->GetVirAddr());
if (!DoDraw(addr, buffer->GetWidth(), buffer->GetHeight(), color)) {
WLOGE("draw window color failed");
return false;
}
OHOS::BufferFlushConfig flushConfig = {
.damage = {
.w = buffer->GetWidth(),
.h = buffer->GetHeight(),
},
};
OHOS::SurfaceError ret = layer->FlushBuffer(buffer, -1, flushConfig);
if (ret != OHOS::SurfaceError::SURFACE_ERROR_OK) {
WLOGFE("draw pointer FlushBuffer ret:%{public}s", SurfaceErrorStr(ret).c_str());
return false;
}
return true;
}
sptr<OHOS::Surface> SurfaceDraw::GetLayer(std::shared_ptr<OHOS::Rosen::RSSurfaceNode> surfaceNode)
{
if (surfaceNode == nullptr) {
return nullptr;
}
return surfaceNode->GetSurface();
}
sptr<OHOS::SurfaceBuffer> SurfaceDraw::GetSurfaceBuffer(sptr<OHOS::Surface> layer,
int32_t bufferWidth, int32_t bufferHeight)
{
sptr<OHOS::SurfaceBuffer> buffer;
int32_t releaseFence = 0;
OHOS::BufferRequestConfig config = {
.width = bufferWidth,
.height = bufferHeight,
.strideAlignment = 0x8,
.format = PIXEL_FMT_RGBA_8888,
.usage = HBM_USE_CPU_READ | HBM_USE_CPU_WRITE | HBM_USE_MEM_DMA,
};
OHOS::SurfaceError ret = layer->RequestBuffer(buffer, releaseFence, config);
if (ret != OHOS::SURFACE_ERROR_OK) {
WLOGFE("request buffer ret:%{public}s", SurfaceErrorStr(ret).c_str());
return nullptr;
}
return buffer;
}
std::unique_ptr<OHOS::Media::PixelMap> SurfaceDraw::DecodeImageToPixelMap(const std::string &imagePath)
{
OHOS::Media::SourceOptions opts;
opts.formatHint = "image/png";
uint32_t ret = 0;
auto imageSource = OHOS::Media::ImageSource::CreateImageSource(imagePath, opts, ret);
if (imageSource == nullptr) {
WLOGFE("invalid image path.");
return nullptr;
}
std::set<std::string> formats;
ret = imageSource->GetSupportedFormats(formats);
WLOGFD("get supported format ret:%{public}u", ret);
OHOS::Media::DecodeOptions decodeOpts;
std::unique_ptr<OHOS::Media::PixelMap> pixelMap = imageSource->CreatePixelMap(decodeOpts, ret);
if (pixelMap == nullptr) {
WLOGFE("pixelMap is nullptr");
}
return pixelMap;
}
void SurfaceDraw::DrawPixelmap(OHOS::Rosen::Drawing::Canvas &canvas, const std::string& imagePath)
{
std::unique_ptr<OHOS::Media::PixelMap> pixelmap = DecodeImageToPixelMap(imagePath);
if (pixelmap == nullptr) {
WLOGFE("drawing pixel map is nullptr");
return;
}
OHOS::Rosen::Drawing::Pen pen;
pen.SetAntiAlias(true);
pen.SetColor(OHOS::Rosen::Drawing::Color::COLOR_BLUE);
OHOS::Rosen::Drawing::scalar penWidth = 1;
pen.SetWidth(penWidth);
canvas.AttachPen(pen);
canvas.DrawBitmap(*pixelmap, 0, 0);
}
bool SurfaceDraw::DoDraw(uint8_t *addr, uint32_t width, uint32_t height, const std::string& imagePath)
{
OHOS::Rosen::Drawing::Bitmap bitmap;
OHOS::Rosen::Drawing::BitmapFormat format { OHOS::Rosen::Drawing::ColorType::COLORTYPE_RGBA_8888,
OHOS::Rosen::Drawing::AlphaType::ALPHATYPE_OPAQUYE };
bitmap.Build(width, height, format);
OHOS::Rosen::Drawing::Canvas canvas;
canvas.Bind(bitmap);
canvas.Clear(OHOS::Rosen::Drawing::Color::COLOR_TRANSPARENT);
DrawPixelmap(canvas, imagePath);
static constexpr uint32_t stride = 4;
uint32_t addrSize = width * height * stride;
errno_t ret = memcpy_s(addr, addrSize, bitmap.GetPixels(), addrSize);
if (ret != EOK) {
WLOGFE("draw failed");
return false;
}
return true;
}
bool SurfaceDraw::DoDraw(uint8_t *addr, uint32_t width, uint32_t height, uint32_t color)
{
OHOS::Rosen::Drawing::Bitmap bitmap;
OHOS::Rosen::Drawing::BitmapFormat format { OHOS::Rosen::Drawing::ColorType::COLORTYPE_RGBA_8888,
OHOS::Rosen::Drawing::AlphaType::ALPHATYPE_OPAQUYE };
bitmap.Build(width, height, format);
OHOS::Rosen::Drawing::Canvas canvas;
canvas.Bind(bitmap);
canvas.Clear(color);
static constexpr uint32_t stride = 4;
uint32_t addrSize = width * height * stride;
errno_t ret = memcpy_s(addr, addrSize, bitmap.GetPixels(), addrSize);
if (ret != EOK) {
WLOGFE("draw failed");
return false;
}
return true;
}
bool SurfaceDraw::DrawImageRect(std::shared_ptr<RSSurfaceNode> surfaceNode, Rect rect,
sptr<Media::PixelMap> pixelMap, uint32_t color)
{
int32_t winHeight = static_cast<int32_t>(rect.height_);
int32_t winWidth = static_cast<int32_t>(rect.width_);
sptr<OHOS::Surface> layer = GetLayer(surfaceNode);
if (layer == nullptr) {
WLOGFE("layer is nullptr");
return false;
}
sptr<OHOS::SurfaceBuffer> buffer = GetSurfaceBuffer(layer, winWidth, winHeight);
if (buffer == nullptr || buffer->GetVirAddr() == nullptr) {
return false;
}
auto addr = static_cast<uint8_t *>(buffer->GetVirAddr());
if (!DoDrawImageRect(addr, winWidth, winHeight, pixelMap, color)) {
WLOGE("draw image rect failed.");
return false;
}
OHOS::BufferFlushConfig flushConfig = {
.damage = {
.w = buffer->GetWidth(),
.h = buffer->GetHeight(),
},
};
OHOS::SurfaceError surfaceRet = layer->FlushBuffer(buffer, -1, flushConfig);
if (surfaceRet != OHOS::SurfaceError::SURFACE_ERROR_OK) {
WLOGFE("draw pointer FlushBuffer ret:%{public}s", SurfaceErrorStr(surfaceRet).c_str());
return false;
}
return true;
}
bool SurfaceDraw::DoDrawImageRect(uint8_t *addr, int32_t winWidth, int32_t winHeight,
sptr<Media::PixelMap> pixelMap, uint32_t color)
{
OHOS::Rosen::Drawing::Bitmap bitmap;
OHOS::Rosen::Drawing::BitmapFormat format { OHOS::Rosen::Drawing::ColorType::COLORTYPE_RGBA_8888,
OHOS::Rosen::Drawing::AlphaType::ALPHATYPE_OPAQUYE };
bitmap.Build(winWidth, winHeight, format);
OHOS::Rosen::Drawing::Canvas canvas;
canvas.Bind(bitmap);
canvas.Clear(color);
if (pixelMap == nullptr) {
WLOGFE("drawing pixel map is nullptr");
return false;
}
uint32_t iconHeight = pixelMap->GetHeight();
uint32_t iconWidth = pixelMap->GetWidth();
Drawing::Image image;
OHOS::Rosen::Drawing::Bitmap iconBitmap;
iconBitmap.Build(iconWidth, iconHeight, format);
iconBitmap.SetPixels(const_cast<uint8_t*>(pixelMap->GetPixels()));
image.BuildFromBitmap(iconBitmap);
Drawing::SamplingOptions sampling = Drawing::SamplingOptions(Drawing::FilterMode::NEAREST,
Drawing::MipmapMode::NEAREST);
int realHeight = std::min(winHeight, pixelMap->GetHeight()); // need to scale
int realWidth = std::min(winWidth, pixelMap->GetWidth());
int pointX = (winWidth - realWidth) / 2; // 2 is mid point
int pointY = (winHeight - realHeight) / 2; // 2 is mid point
Drawing::Rect dst(pointX, pointY, pointX + realWidth, pointY + realHeight);
canvas.DrawImageRect(image, dst, sampling);
uint32_t stride = 4;
uint32_t addrSize = winWidth * winHeight * stride;
errno_t ret = memcpy_s(addr, addrSize, bitmap.GetPixels(), addrSize);
if (ret != EOK) {
WLOGFE("draw failed");
return false;
}
return true;
}
} // Rosen
} // OHOS