1 /*
2  * Copyright (c) 2024 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 "render/rs_hps_blur.h"
17 
18 #include "common/rs_optional_trace.h"
19 #include "draw/surface.h"
20 #include "effect/runtime_shader_builder.h"
21 #include "platform/common/rs_log.h"
22 #include "platform/common/rs_system_properties.h"
23 
24 
25 namespace OHOS {
26 namespace Rosen {
27 
28 static constexpr uint32_t MAX_SURFACE_SIZE = 10000;
29 
GetShaderTransform(const Drawing::Rect & blurRect,float scaleW,float scaleH)30 Drawing::Matrix HpsBlurFilter::GetShaderTransform(const Drawing::Rect& blurRect, float scaleW, float scaleH)
31 {
32     Drawing::Matrix matrix;
33     matrix.SetScale(scaleW, scaleH);
34     Drawing::Matrix translateMatrix;
35     translateMatrix.Translate(blurRect.GetLeft(), blurRect.GetTop());
36     matrix.PostConcat(translateMatrix);
37     return matrix;
38 }
39 
ApplyHpsBlur(Drawing::Canvas & canvas,const std::shared_ptr<Drawing::Image> & image,const Drawing::HpsBlurParameter & param,float alpha) const40 bool HpsBlurFilter::ApplyHpsBlur(Drawing::Canvas& canvas, const std::shared_ptr<Drawing::Image>& image,
41     const Drawing::HpsBlurParameter& param, float alpha) const
42 {
43     auto surface = canvas.GetSurface();
44     if (surface == nullptr || image == nullptr) {
45         return false;
46     }
47     std::array<int, 2> dimension = canvas.CalcHpsBluredImageDimension(param); // There are 2 variables
48     if (dimension[0] <= 0 || dimension[1] <= 0 || dimension[0] >= static_cast<int>(MAX_SURFACE_SIZE)
49         || dimension[1] >= static_cast<int>(MAX_SURFACE_SIZE)) {
50         ROSEN_LOGD("HpsBlurFilter::ApplyHpsBlur CalcHpsBluredImageDimension error");
51         return false;
52     }
53     std::shared_ptr<Drawing::Surface> offscreenSurface = surface->MakeSurface(dimension[0], dimension[1]);
54     if (offscreenSurface == nullptr) {
55         return false;
56     }
57 
58     std::shared_ptr<Drawing::Canvas> offscreenCanvas = offscreenSurface->GetCanvas();
59     if (offscreenCanvas == nullptr) {
60         return false;
61     }
62     Drawing::Rect dimensionRect = {0, 0, dimension[0], dimension[1]};
63     auto offscreenHpsParam = Drawing::HpsBlurParameter(param.src, dimensionRect, param.sigma,
64         param.saturation, param.brightness);
65     if (!offscreenCanvas->DrawBlurImage(*image, offscreenHpsParam)) {
66         return false;
67     }
68 
69     auto imageCache = offscreenSurface->GetImageSnapshot();
70     if (imageCache == nullptr) {
71         return false;
72     }
73     auto dst = param.dst;
74     Drawing::SamplingOptions linear(Drawing::FilterMode::LINEAR, Drawing::MipmapMode::NONE);
75     const auto blurMatrix = GetShaderTransform(dst, dst.GetWidth() / imageCache->GetWidth(),
76         dst.GetHeight() / imageCache->GetHeight());
77     const auto blurShader = Drawing::ShaderEffect::CreateImageShader(*imageCache, Drawing::TileMode::CLAMP,
78         Drawing::TileMode::CLAMP, linear, blurMatrix);
79     Drawing::Brush brush;
80     brush.SetAlphaF(alpha);
81     brush.SetShaderEffect(blurShader);
82     canvas.AttachBrush(brush);
83     canvas.DrawRect(dst);
84     canvas.DetachBrush();
85     return true;
86 }
87 } // namespace Rosen
88 } // namespace OHOS