1 /*
2 * Copyright (c) 2021-2023 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_blur_filter.h"
17
18 #include "src/core/SkOpts.h"
19
20 #include "common/rs_common_def.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 const bool KAWASE_BLUR_ENABLED = RSSystemProperties::GetKawaseEnabled();
28 const auto BLUR_TYPE = KAWASE_BLUR_ENABLED ? Drawing::ImageBlurType::KAWASE : Drawing::ImageBlurType::GAUSS;
RSBlurFilter(float blurRadiusX,float blurRadiusY)29 RSBlurFilter::RSBlurFilter(float blurRadiusX, float blurRadiusY) : RSDrawingFilterOriginal(
30 Drawing::ImageFilter::CreateBlurImageFilter(blurRadiusX, blurRadiusY, Drawing::TileMode::CLAMP, nullptr,
31 BLUR_TYPE)),
32 blurRadiusX_(blurRadiusX),
33 blurRadiusY_(blurRadiusY)
34 {
35 type_ = FilterType::BLUR;
36
37 float blurRadiusXForHash = DecreasePrecision(blurRadiusX);
38 float blurRadiusYForHash = DecreasePrecision(blurRadiusY);
39 hash_ = SkOpts::hash(&type_, sizeof(type_), 0);
40 hash_ = SkOpts::hash(&blurRadiusXForHash, sizeof(blurRadiusXForHash), hash_);
41 hash_ = SkOpts::hash(&blurRadiusYForHash, sizeof(blurRadiusYForHash), hash_);
42 }
43
44 RSBlurFilter::~RSBlurFilter() = default;
45
GetBlurRadiusX()46 float RSBlurFilter::GetBlurRadiusX()
47 {
48 return blurRadiusX_;
49 }
50
GetBlurRadiusY()51 float RSBlurFilter::GetBlurRadiusY()
52 {
53 return blurRadiusY_;
54 }
55
GetDescription()56 std::string RSBlurFilter::GetDescription()
57 {
58 return "RSBlurFilter blur radius is " + std::to_string(blurRadiusX_) + " sigma";
59 }
60
GetDetailedDescription()61 std::string RSBlurFilter::GetDetailedDescription()
62 {
63 return "RSBlurFilterBlur, radius: " + std::to_string(blurRadiusX_) + " sigma" +
64 ", greyCoef1: " + std::to_string(greyCoef_ == std::nullopt ? 0.0f : greyCoef_->x_) +
65 ", greyCoef2: " + std::to_string(greyCoef_ == std::nullopt ? 0.0f : greyCoef_->y_);
66 }
67
IsValid() const68 bool RSBlurFilter::IsValid() const
69 {
70 constexpr float epsilon = 0.999f;
71 return blurRadiusX_ > epsilon || blurRadiusY_ > epsilon;
72 }
73
Compose(const std::shared_ptr<RSDrawingFilterOriginal> & other) const74 std::shared_ptr<RSDrawingFilterOriginal> RSBlurFilter::Compose(
75 const std::shared_ptr<RSDrawingFilterOriginal>& other) const
76 {
77 std::shared_ptr<RSBlurFilter> result = std::make_shared<RSBlurFilter>(blurRadiusX_, blurRadiusY_);
78 result->imageFilter_ = Drawing::ImageFilter::CreateComposeImageFilter(imageFilter_, other->GetImageFilter());
79 auto otherHash = other->Hash();
80 result->hash_ = SkOpts::hash(&otherHash, sizeof(otherHash), hash_);
81 return result;
82 }
83
Add(const std::shared_ptr<RSFilter> & rhs)84 std::shared_ptr<RSFilter> RSBlurFilter::Add(const std::shared_ptr<RSFilter>& rhs)
85 {
86 if ((rhs == nullptr) || (rhs->GetFilterType() != FilterType::BLUR)) {
87 return shared_from_this();
88 }
89 auto blurR = std::static_pointer_cast<RSBlurFilter>(rhs);
90 return std::make_shared<RSBlurFilter>(
91 blurRadiusX_ + blurR->GetBlurRadiusX(), blurRadiusY_ + blurR->GetBlurRadiusY());
92 }
93
Sub(const std::shared_ptr<RSFilter> & rhs)94 std::shared_ptr<RSFilter> RSBlurFilter::Sub(const std::shared_ptr<RSFilter>& rhs)
95 {
96 if ((rhs == nullptr) || (rhs->GetFilterType() != FilterType::BLUR)) {
97 return shared_from_this();
98 }
99 auto blurR = std::static_pointer_cast<RSBlurFilter>(rhs);
100 return std::make_shared<RSBlurFilter>(
101 blurRadiusX_ - blurR->GetBlurRadiusX(), blurRadiusY_ - blurR->GetBlurRadiusY());
102 }
103
Multiply(float rhs)104 std::shared_ptr<RSFilter> RSBlurFilter::Multiply(float rhs)
105 {
106 return std::make_shared<RSBlurFilter>(blurRadiusX_ * rhs, blurRadiusY_ * rhs);
107 }
108
Negate()109 std::shared_ptr<RSFilter> RSBlurFilter::Negate()
110 {
111 return std::make_shared<RSBlurFilter>(-blurRadiusX_, -blurRadiusY_);
112 }
113
IsNearEqual(const std::shared_ptr<RSFilter> & other,float threshold) const114 bool RSBlurFilter::IsNearEqual(const std::shared_ptr<RSFilter>& other, float threshold) const
115 {
116 auto otherBlurFilter = std::static_pointer_cast<RSBlurFilter>(other);
117 if (otherBlurFilter == nullptr) {
118 ROSEN_LOGE("RSBlurFilter::IsNearEqual: the types of filters are different.");
119 return true;
120 }
121 return ROSEN_EQ(blurRadiusX_, otherBlurFilter->GetBlurRadiusX(), threshold) &&
122 ROSEN_EQ(blurRadiusY_, otherBlurFilter->GetBlurRadiusY(), threshold);
123 }
124
IsNearZero(float threshold) const125 bool RSBlurFilter::IsNearZero(float threshold) const
126 {
127 return ROSEN_EQ(blurRadiusX_, 0.0f, threshold) && ROSEN_EQ(blurRadiusY_, 0.0f, threshold);
128 }
129
IsEqual(const std::shared_ptr<RSFilter> & other) const130 bool RSBlurFilter::IsEqual(const std::shared_ptr<RSFilter>& other) const
131 {
132 auto otherBlurFilter = std::static_pointer_cast<RSBlurFilter>(other);
133 if (otherBlurFilter == nullptr) {
134 ROSEN_LOGE("RSBlurFilter::IsEqual: the types of filters are different.");
135 return true;
136 }
137 return ROSEN_EQ(blurRadiusX_, otherBlurFilter->GetBlurRadiusX()) &&
138 ROSEN_EQ(blurRadiusY_, otherBlurFilter->GetBlurRadiusY());
139 }
140
IsEqualZero() const141 bool RSBlurFilter::IsEqualZero() const
142 {
143 return ROSEN_EQ(blurRadiusX_, 0.0f) && ROSEN_EQ(blurRadiusY_, 0.0f);
144 }
145
DrawImageRect(Drawing::Canvas & canvas,const std::shared_ptr<Drawing::Image> & image,const Drawing::Rect & src,const Drawing::Rect & dst) const146 void RSBlurFilter::DrawImageRect(Drawing::Canvas& canvas, const std::shared_ptr<Drawing::Image>& image,
147 const Drawing::Rect& src, const Drawing::Rect& dst) const
148 {
149 auto brush = GetBrush();
150 std::shared_ptr<Drawing::Image> greyImage = image;
151 if (greyCoef_.has_value()) {
152 greyImage = RSPropertiesPainter::DrawGreyAdjustment(canvas, image, greyCoef_.value());
153 }
154 if (greyImage == nullptr) {
155 greyImage = image;
156 }
157 // if kawase blur failed, use gauss blur
158 static bool DDGR_ENABLED = RSSystemProperties::GetGpuApiType() == GpuApiType::DDGR;
159 KawaseParameter param = KawaseParameter(src, dst, blurRadiusX_, nullptr, brush.GetColor().GetAlphaF());
160 if (!DDGR_ENABLED && KAWASE_BLUR_ENABLED &&
161 KawaseBlurFilter::GetKawaseBlurFilter()->ApplyKawaseBlur(canvas, greyImage, param)) {
162 return;
163 }
164 canvas.AttachBrush(brush);
165 canvas.DrawImageRect(*greyImage, src, dst, Drawing::SamplingOptions());
166 canvas.DetachBrush();
167 }
168
SetGreyCoef(const std::optional<Vector2f> & greyCoef)169 void RSBlurFilter::SetGreyCoef(const std::optional<Vector2f>& greyCoef)
170 {
171 greyCoef_ = greyCoef;
172 }
173
CanSkipFrame() const174 bool RSBlurFilter::CanSkipFrame() const
175 {
176 constexpr float HEAVY_BLUR_THRESHOLD = 25.0f;
177 return blurRadiusX_ > HEAVY_BLUR_THRESHOLD && blurRadiusY_ > HEAVY_BLUR_THRESHOLD;
178 };
179 } // namespace Rosen
180 } // namespace OHOS
181