• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 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 #include "render/rs_material_filter.h"
16 
17 #include <unordered_map>
18 
19 #include "src/core/SkOpts.h"
20 
21 #include "common/rs_common_def.h"
22 #include "pipeline/rs_paint_filter_canvas.h"
23 #include "property/rs_properties_painter.h"
24 #include "platform/common/rs_system_properties.h"
25 
26 #if defined(NEW_SKIA)
27 #include "include/effects/SkImageFilters.h"
28 #include "include/core/SkTileMode.h"
29 #else
30 #include "include/effects/SkBlurImageFilter.h"
31 #endif
32 
33 namespace OHOS {
34 namespace Rosen {
35 namespace {
36 constexpr float BLUR_SIGMA_SCALE = 0.57735f;
37 // style to MaterialParam map
38 std::unordered_map<MATERIAL_BLUR_STYLE, MaterialParam> materialParams_ {
39     // card blur params
40     { STYLE_CARD_THIN_LIGHT,         { 23.0f,  1.05, 1.05, RSColor(0xFFFFFF33) } },
41     { STYLE_CARD_LIGHT,              { 50.0f,  1.8,  1.2,  RSColor(0xFAFAFA99) } },
42     { STYLE_CARD_THICK_LIGHT,        { 57.0f,  1.2,  1.1,  RSColor(0xFFFFFF8C) } },
43     { STYLE_CARD_THIN_DARK,          { 75.0f,  1.35, 1.0,  RSColor(0x1A1A1A6B) } },
44     { STYLE_CARD_DARK,               { 50.0f,  2.15, 1.0,  RSColor(0x1F1F1FD1) } },
45     { STYLE_CARD_THICK_DARK,         { 75.0f,  2.15, 1.0,  RSColor(0x1F1F1FD1) } },
46     // background blur params
47     { STYLE_BACKGROUND_SMALL_LIGHT,  { 23.0f,  1.05, 1.0,  RSColor(0x80808033) } },
48     { STYLE_BACKGROUND_MEDIUM_LIGHT, { 29.0f,  1.1,  1.0,  RSColor(0x80808033) } },
49     { STYLE_BACKGROUND_LARGE_LIGHT,  { 57.0f,  1.2,  1.0,  RSColor(0x80808033) } },
50     { STYLE_BACKGROUND_XLARGE_LIGHT, { 120.0f, 1.3,  1.0,  RSColor(0x6666664C) } },
51     { STYLE_BACKGROUND_SMALL_DARK,   { 15.0f,  1.1,  1.0,  RSColor(0x0D0D0D80) } },
52     { STYLE_BACKGROUND_MEDIUM_DARK,  { 55.0f,  1.15, 1.0,  RSColor(0x0D0D0D80) } },
53     { STYLE_BACKGROUND_LARGE_DARK,   { 75.0f,  1.5,  1.0,  RSColor(0x0D0D0D80) } },
54     { STYLE_BACKGROUND_XLARGE_DARK,  { 130.0f, 1.3,  1.0,  RSColor(0x0D0D0D80) } },
55 };
56 } // namespace
57 
58 #ifndef USE_ROSEN_DRAWING
59 std::shared_ptr<KawaseBlurFilter> RSMaterialFilter::kawaseFunc_ = std::make_shared<KawaseBlurFilter>();
60 #endif
61 
RSMaterialFilter(int style,float dipScale,BLUR_COLOR_MODE mode,float ratio)62 RSMaterialFilter::RSMaterialFilter(int style, float dipScale, BLUR_COLOR_MODE mode, float ratio)
63 #ifndef USE_ROSEN_DRAWING
64     : RSSkiaFilter(nullptr), colorMode_(mode)
65 #else
66     : RSDrawingFilter(nullptr), colorMode_(mode)
67 #endif
68 {
69     imageFilter_ = RSMaterialFilter::CreateMaterialStyle(static_cast<MATERIAL_BLUR_STYLE>(style), dipScale, ratio);
70     type_ = FilterType::MATERIAL;
71 
72 #ifndef USE_ROSEN_DRAWING
73     hash_ = SkOpts::hash(&type_, sizeof(type_), 0);
74     hash_ = SkOpts::hash(&style, sizeof(style), hash_);
75     hash_ = SkOpts::hash(&colorMode_, sizeof(colorMode_), hash_);
76     hash_ = SkOpts::hash(&ratio, sizeof(ratio), hash_);
77 #endif
78 }
79 
RSMaterialFilter(MaterialParam materialParam,BLUR_COLOR_MODE mode)80 RSMaterialFilter::RSMaterialFilter(MaterialParam materialParam, BLUR_COLOR_MODE mode)
81 #ifndef USE_ROSEN_DRAWING
82     : RSSkiaFilter(nullptr), colorMode_(mode), radius_(materialParam.radius), saturation_(materialParam.saturation),
83 #else
84     : RSDrawingFilter(nullptr), colorMode_(mode), radius_(materialParam.radius), saturation_(materialParam.saturation),
85 #endif
86       brightness_(materialParam.brightness), maskColor_(materialParam.maskColor)
87 {
88     imageFilter_ = RSMaterialFilter::CreateMaterialFilter(
89         materialParam.radius, materialParam.saturation, materialParam.brightness);
90     type_ = FilterType::MATERIAL;
91 
92 #ifndef USE_ROSEN_DRAWING
93     hash_ = SkOpts::hash(&type_, sizeof(type_), 0);
94     hash_ = SkOpts::hash(&materialParam, sizeof(materialParam), hash_);
95     hash_ = SkOpts::hash(&colorMode_, sizeof(colorMode_), hash_);
96 #endif
97 }
98 
99 RSMaterialFilter::~RSMaterialFilter() = default;
100 
RadiusVp2Sigma(float radiusVp,float dipScale)101 float RSMaterialFilter::RadiusVp2Sigma(float radiusVp, float dipScale)
102 {
103     float radiusPx = radiusVp * dipScale;
104 #ifndef USE_ROSEN_DRAWING
105     return radiusPx > 0.0f ? BLUR_SIGMA_SCALE * radiusPx + SK_ScalarHalf : 0.0f;
106 #else
107     return radiusPx > 0.0f ? BLUR_SIGMA_SCALE * radiusPx + 0.5f : 0.0f;
108 #endif
109 }
110 
GetDescription()111 std::string RSMaterialFilter::GetDescription()
112 {
113     return "RSMaterialFilter blur radius is " + std::to_string(radius_) + " sigma";
114 }
115 
116 #ifndef USE_ROSEN_DRAWING
Compose(const std::shared_ptr<RSSkiaFilter> & other) const117 std::shared_ptr<RSSkiaFilter> RSMaterialFilter::Compose(const std::shared_ptr<RSSkiaFilter>& other) const
118 #else
119 std::shared_ptr<RSDrawingFilter> RSMaterialFilter::Compose(const std::shared_ptr<RSDrawingFilter>& other) const
120 #endif
121 {
122     if (other == nullptr) {
123         return nullptr;
124     }
125     MaterialParam materialParam = {radius_, saturation_, brightness_, maskColor_};
126     std::shared_ptr<RSMaterialFilter> result = std::make_shared<RSMaterialFilter>(materialParam, colorMode_);
127 #ifndef USE_ROSEN_DRAWING
128     result->imageFilter_ = SkImageFilters::Compose(imageFilter_, other->GetImageFilter());
129     auto otherHash = other->Hash();
130     result->hash_ = SkOpts::hash(&otherHash, sizeof(otherHash), hash_);
131 #else
132     result->imageFilter_ = Drawing::ImageFilter::CreateComposeImageFilter(imageFilter_, other->GetImageFilter());
133 #endif
134     return result;
135 }
136 
137 #ifndef USE_ROSEN_DRAWING
GetColorFilter(float sat,float brightness)138 sk_sp<SkColorFilter> RSMaterialFilter::GetColorFilter(float sat, float brightness)
139 {
140     float normalizedDegree = brightness - 1.0;
141     const float brightnessMat[] = {
142         1.000000f, 0.000000f, 0.000000f, 0.000000f, normalizedDegree,
143         0.000000f, 1.000000f, 0.000000f, 0.000000f, normalizedDegree,
144         0.000000f, 0.000000f, 1.000000f, 0.000000f, normalizedDegree,
145         0.000000f, 0.000000f, 0.000000f, 1.000000f, 0.000000f,
146     };
147 
148     sk_sp<SkColorFilter> brightnessFilter = SkColorFilters::Matrix(brightnessMat); // brightness
149     SkColorMatrix cm;
150     cm.setSaturation(sat);
151     sk_sp<SkColorFilter> satFilter = SkColorFilters::Matrix(cm); // saturation
152     sk_sp<SkColorFilter> filterCompose = SkColorFilters::Compose(satFilter, brightnessFilter);
153     return filterCompose;
154 }
155 
CreateMaterialFilter(float radius,float sat,float brightness)156 sk_sp<SkImageFilter> RSMaterialFilter::CreateMaterialFilter(float radius, float sat, float brightness)
157 {
158     colorFilter_ = GetColorFilter(sat, brightness);
159 #if defined(NEW_SKIA)
160     useKawase_ = RSSystemProperties::GetKawaseEnabled();
161     sk_sp<SkImageFilter> blurFilter = SkImageFilters::Blur(radius, radius, SkTileMode::kClamp, nullptr); // blur
162 #else
163     sk_sp<SkImageFilter> blurFilter = SkBlurImageFilter::Make(radius, radius, nullptr, nullptr,
164         SkBlurImageFilter::kClamp_TileMode); // blur
165 #endif
166 
167     return SkImageFilters::ColorFilter(colorFilter_, blurFilter);
168 }
169 #else
CreateMaterialFilter(float radius,float sat,float brightness)170 std::shared_ptr<Drawing::ImageFilter> RSMaterialFilter::CreateMaterialFilter(float radius, float sat, float brightness)
171 {
172     std::shared_ptr<Drawing::ImageFilter> blurFilter =
173         Drawing::ImageFilter::CreateBlurImageFilter(radius, radius, Drawing::TileMode::CLAMP, nullptr);
174     float normalizedDegree = brightness - 1.0;
175     const Drawing::scalar brightnessMat[] = {
176         1.000000f, 0.000000f, 0.000000f, 0.000000f, normalizedDegree,
177         0.000000f, 1.000000f, 0.000000f, 0.000000f, normalizedDegree,
178         0.000000f, 0.000000f, 1.000000f, 0.000000f, normalizedDegree,
179         0.000000f, 0.000000f, 0.000000f, 1.000000f, 0.000000f,
180     };
181 
182     Drawing::ColorMatrix bm;
183     bm.SetArray(brightnessMat);
184     std::shared_ptr<Drawing::ColorFilter> brightnessFilter =
185         Drawing::ColorFilter::CreateMatrixColorFilter(bm); // brightness
186     Drawing::ColorMatrix cm;
187     cm.SetSaturation(sat);
188     std::shared_ptr<Drawing::ColorFilter> satFilter = Drawing::ColorFilter::CreateMatrixColorFilter(cm); // saturation
189     std::shared_ptr<Drawing::ColorFilter> filterCompose =
190         Drawing::ColorFilter::CreateComposeColorFilter(*brightnessFilter, *satFilter); // saturation
191 
192     return Drawing::ImageFilter::CreateColorFilterImageFilter(*filterCompose, blurFilter);
193 }
194 #endif
195 
196 #ifndef USE_ROSEN_DRAWING
CreateMaterialStyle(MATERIAL_BLUR_STYLE style,float dipScale,float ratio)197 sk_sp<SkImageFilter> RSMaterialFilter::CreateMaterialStyle(MATERIAL_BLUR_STYLE style, float dipScale, float ratio)
198 #else
199 std::shared_ptr<Drawing::ImageFilter> RSMaterialFilter::CreateMaterialStyle(
200     MATERIAL_BLUR_STYLE style, float dipScale, float ratio)
201 #endif
202 {
203     if (materialParams_.find(style) != materialParams_.end()) {
204         MaterialParam materialParam = materialParams_[style];
205         maskColor_ = RSColor(materialParam.maskColor.AsRgbaInt());
206         maskColor_.MultiplyAlpha(ratio);
207         radius_ = RSMaterialFilter::RadiusVp2Sigma(materialParam.radius, dipScale) * ratio;
208         saturation_ = (materialParam.saturation - 1) * ratio + 1.0;
209         brightness_ = (materialParam.brightness - 1) * ratio + 1.0;
210         return RSMaterialFilter::CreateMaterialFilter(radius_, saturation_, brightness_);
211     }
212     return nullptr;
213 }
214 
215 #ifndef USE_ROSEN_DRAWING
PreProcess(sk_sp<SkImage> imageSnapshot)216 void RSMaterialFilter::PreProcess(sk_sp<SkImage> imageSnapshot)
217 {
218     if (colorMode_ == AVERAGE && imageSnapshot != nullptr) {
219         // update maskColor while persevere alpha
220         SkColor colorPicker = RSPropertiesPainter::CalcAverageColor(imageSnapshot);
221         maskColor_ = RSColor(
222             SkColorGetR(colorPicker), SkColorGetG(colorPicker), SkColorGetB(colorPicker), maskColor_.GetAlpha());
223     }
224 }
225 #else
PreProcess(std::shared_ptr<Drawing::Image> imageSnapshot)226 void RSMaterialFilter::PreProcess(std::shared_ptr<Drawing::Image> imageSnapshot)
227 {
228     if (colorMode_ == AVERAGE && imageSnapshot != nullptr) {
229         // update maskColor while persevere alpha
230         auto colorPicker = RSPropertiesPainter::CalcAverageColor(imageSnapshot);
231         maskColor_ = RSColor(Drawing::Color::ColorQuadGetR(colorPicker), Drawing::Color::ColorQuadGetG(colorPicker),
232             Drawing::Color::ColorQuadGetB(colorPicker), maskColor_.GetAlpha());
233     }
234 }
235 #endif
236 
PostProcess(RSPaintFilterCanvas & canvas)237 void RSMaterialFilter::PostProcess(RSPaintFilterCanvas& canvas)
238 {
239 #ifndef USE_ROSEN_DRAWING
240     SkPaint paint;
241     paint.setColor(maskColor_.AsArgbInt());
242     canvas.drawPaint(paint);
243 #else
244     Drawing::Brush brush;
245     brush.SetColor(maskColor_.AsArgbInt());
246     canvas.DrawBackground(brush);
247 #endif
248 }
249 
TransformFilter(float fraction) const250 std::shared_ptr<RSFilter> RSMaterialFilter::TransformFilter(float fraction) const
251 {
252     MaterialParam materialParam;
253     materialParam.radius = radius_ * fraction;
254     materialParam.saturation = (saturation_ - 1) * fraction + 1.0;
255     materialParam.brightness = (brightness_ - 1) * fraction + 1.0;
256     materialParam.maskColor = RSColor(maskColor_.GetRed(), maskColor_.GetGreen(),
257         maskColor_.GetBlue(), maskColor_.GetAlpha() * fraction);
258     return std::make_shared<RSMaterialFilter>(materialParam, colorMode_);
259 }
260 
IsValid() const261 bool RSMaterialFilter::IsValid() const
262 {
263     constexpr float epsilon = 0.001f;
264     if (ROSEN_EQ(radius_, 0.f, epsilon)) {
265         return false;
266     }
267     return true;
268 }
269 
Add(const std::shared_ptr<RSFilter> & rhs)270 std::shared_ptr<RSFilter> RSMaterialFilter::Add(const std::shared_ptr<RSFilter>& rhs)
271 {
272     if ((rhs == nullptr) || (rhs->GetFilterType() != FilterType::MATERIAL)) {
273         return shared_from_this();
274     }
275     auto materialR = std::static_pointer_cast<RSMaterialFilter>(rhs);
276 
277     MaterialParam materialParam;
278     materialParam.radius = radius_ + materialR->radius_;
279     materialParam.saturation = saturation_ + materialR->saturation_;
280     materialParam.brightness = brightness_ + materialR->brightness_;
281     materialParam.maskColor = maskColor_ + materialR->maskColor_;
282     return std::make_shared<RSMaterialFilter>(materialParam, materialR->colorMode_);
283 }
284 
Sub(const std::shared_ptr<RSFilter> & rhs)285 std::shared_ptr<RSFilter> RSMaterialFilter::Sub(const std::shared_ptr<RSFilter>& rhs)
286 {
287     if ((rhs == nullptr) || (rhs->GetFilterType() != FilterType::MATERIAL)) {
288         return shared_from_this();
289     }
290     auto materialR = std::static_pointer_cast<RSMaterialFilter>(rhs);
291     MaterialParam materialParam;
292     materialParam.radius = radius_ - materialR->radius_;
293     materialParam.saturation = saturation_ - materialR->saturation_;
294     materialParam.brightness = brightness_ - materialR->brightness_;
295     materialParam.maskColor = maskColor_ - materialR->maskColor_;
296     return std::make_shared<RSMaterialFilter>(materialParam, materialR->colorMode_);
297 }
298 
Multiply(float rhs)299 std::shared_ptr<RSFilter> RSMaterialFilter::Multiply(float rhs)
300 {
301     MaterialParam materialParam;
302     materialParam.radius = radius_ * rhs;
303     materialParam.saturation = saturation_ * rhs;
304     materialParam.brightness = brightness_ * rhs;
305     materialParam.maskColor = maskColor_ * rhs;
306     return std::make_shared<RSMaterialFilter>(materialParam, colorMode_);
307 }
308 
Negate()309 std::shared_ptr<RSFilter> RSMaterialFilter::Negate()
310 {
311     MaterialParam materialParam;
312     materialParam.radius = -radius_;
313     materialParam.saturation = -saturation_;
314     materialParam.brightness = -brightness_;
315     materialParam.maskColor = RSColor(0x00000000) - maskColor_;
316     return std::make_shared<RSMaterialFilter>(materialParam, colorMode_);
317 }
318 
319 #ifndef USE_ROSEN_DRAWING
DrawImageRect(SkCanvas & canvas,const sk_sp<SkImage> & image,const SkRect & src,const SkRect & dst) const320 void RSMaterialFilter::DrawImageRect(
321     SkCanvas& canvas, const sk_sp<SkImage>& image, const SkRect& src, const SkRect& dst) const
322 #else
323 void RSMaterialFilter::DrawImageRect(Drawing::Canvas& canvas, const std::shared_ptr<Drawing::Image>& image,
324     const Drawing::Rect& src, const Drawing::Rect& dst) const
325 #endif
326 {
327 #ifndef USE_ROSEN_DRAWING
328     auto paint = GetPaint();
329 #ifdef NEW_SKIA
330     // if kawase blur failed, use gauss blur
331     KawaseParameter param = KawaseParameter(src, dst, radius_, colorFilter_, paint.getAlphaf());
332     if (useKawase_ && kawaseFunc_->ApplyKawaseBlur(canvas, image, param)) {
333         return;
334     }
335     canvas.drawImageRect(image.get(), src, dst, SkSamplingOptions(), &paint, SkCanvas::kStrict_SrcRectConstraint);
336 #else
337     canvas.drawImageRect(image.get(), src, dst, &paint);
338 #endif
339 #else
340     auto brush = GetBrush();
341     canvas.AttachBrush(brush);
342     canvas.DrawImageRect(*image, src, dst, Drawing::SamplingOptions());
343     canvas.DetachBrush();
344 #endif
345 }
346 
CanSkipFrame() const347 bool RSMaterialFilter::CanSkipFrame() const
348 {
349     constexpr float HEAVY_BLUR_THRESHOLD = 25.0f;
350     return radius_ > HEAVY_BLUR_THRESHOLD;
351 };
352 } // namespace Rosen
353 } // namespace OHOS
354