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