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 #include "render/rs_material_filter.h"
16
17 #include <unordered_map>
18
19 #ifdef USE_M133_SKIA
20 #include "src/core/SkChecksum.h"
21 #else
22 #include "src/core/SkOpts.h"
23 #endif
24
25 #include "common/rs_common_def.h"
26 #include "common/rs_optional_trace.h"
27 #include "pipeline/rs_paint_filter_canvas.h"
28 #include "platform/common/rs_log.h"
29 #include "property/rs_properties_painter.h"
30 #include "platform/common/rs_system_properties.h"
31
32 #include "include/effects/SkImageFilters.h"
33 #include "include/core/SkTileMode.h"
34
35 namespace OHOS {
36 namespace Rosen {
37 namespace {
38 // style to MaterialParam map
39 static const std::unordered_map<MATERIAL_BLUR_STYLE, MaterialParam> MATERIAL_PARAM {
40 // card blur params
41 { STYLE_CARD_THIN_LIGHT, { 23.0f, 1.05, 1.05, RSColor(0xFFFFFF33) } },
42 { STYLE_CARD_LIGHT, { 50.0f, 1.8, 1.0, RSColor(0xFAFAFA99) } },
43 { STYLE_CARD_THICK_LIGHT, { 57.0f, 1.2, 1.1, RSColor(0xFFFFFF8C) } },
44 { STYLE_CARD_THIN_DARK, { 75.0f, 1.35, 1.0, RSColor(0x1A1A1A6B) } },
45 { STYLE_CARD_DARK, { 50.0f, 2.15, 1.0, RSColor(0x1F1F1FD1) } },
46 { STYLE_CARD_THICK_DARK, { 75.0f, 2.15, 1.0, RSColor(0x1F1F1FD1) } },
47 // background blur params
48 { STYLE_BACKGROUND_SMALL_LIGHT, { 23.0f, 1.05, 1.0, RSColor(0x80808033) } },
49 { STYLE_BACKGROUND_MEDIUM_LIGHT, { 29.0f, 1.1, 1.0, RSColor(0x80808033) } },
50 { STYLE_BACKGROUND_LARGE_LIGHT, { 57.0f, 1.2, 1.0, RSColor(0x80808033) } },
51 { STYLE_BACKGROUND_XLARGE_LIGHT, { 120.0f, 1.3, 1.0, RSColor(0x6666664C) } },
52 { STYLE_BACKGROUND_SMALL_DARK, { 15.0f, 1.1, 1.0, RSColor(0x0D0D0D80) } },
53 { STYLE_BACKGROUND_MEDIUM_DARK, { 55.0f, 1.15, 1.0, RSColor(0x0D0D0D80) } },
54 { STYLE_BACKGROUND_LARGE_DARK, { 75.0f, 1.5, 1.0, RSColor(0x0D0D0D80) } },
55 { STYLE_BACKGROUND_XLARGE_DARK, { 130.0f, 1.3, 1.0, RSColor(0x0D0D0D80) } },
56 };
57
58 static const std::unordered_map<MATERIAL_BLUR_STYLE, MaterialParam> KAWASE_MATERIAL_PARAM {
59 // card blur params
60 { STYLE_CARD_THIN_LIGHT, { 23.0f, 1.05, 1.05, RSColor(0xFFFFFF33) } },
61 { STYLE_CARD_LIGHT, { 50.0f, 1.8, 1.0, RSColor(0xFAFAFA99) } },
62 { STYLE_CARD_THICK_LIGHT, { 57.0f, 1.2, 1.1, RSColor(0xFFFFFF8C) } },
63 { STYLE_CARD_THIN_DARK, { 75.0f, 1.35, 1.0, RSColor(0x1A1A1A6B) } },
64 { STYLE_CARD_DARK, { 50.0f, 2.15, 1.0, RSColor(0x1F1F1FD1) } },
65 { STYLE_CARD_THICK_DARK, { 75.0f, 2.15, 1.0, RSColor(0x1F1F1FD1) } },
66 // background blur params
67 { STYLE_BACKGROUND_SMALL_LIGHT, { 12.0f, 1.05, 1.0, RSColor(0x80808033) } },
68 { STYLE_BACKGROUND_MEDIUM_LIGHT, { 29.0f, 1.1, 1.0, RSColor(0x80808033) } },
69 { STYLE_BACKGROUND_LARGE_LIGHT, { 45.0f, 1.2, 1.0, RSColor(0x80808033) } },
70 { STYLE_BACKGROUND_XLARGE_LIGHT, { 120.0f, 1.3, 1.0, RSColor(0x6666664C) } },
71 { STYLE_BACKGROUND_SMALL_DARK, { 15.0f, 1.1, 1.0, RSColor(0x0D0D0D80) } },
72 { STYLE_BACKGROUND_MEDIUM_DARK, { 55.0f, 1.15, 1.0, RSColor(0x0D0D0D80) } },
73 { STYLE_BACKGROUND_LARGE_DARK, { 75.0f, 1.5, 1.0, RSColor(0x0D0D0D80) } },
74 { STYLE_BACKGROUND_XLARGE_DARK, { 130.0f, 1.3, 1.0, RSColor(0x0D0D0D80) } },
75 };
76 } // namespace
77
78 const bool KAWASE_BLUR_ENABLED = RSSystemProperties::GetKawaseEnabled();
79 const bool HPS_BLUR_ENABLED = RSSystemProperties::GetHpsBlurEnabled();
80
RSMaterialFilter(int style,float dipScale,BLUR_COLOR_MODE mode,float ratio,bool disableSystemAdaptation)81 RSMaterialFilter::RSMaterialFilter(int style, float dipScale, BLUR_COLOR_MODE mode, float ratio,
82 bool disableSystemAdaptation)
83 : RSDrawingFilterOriginal(nullptr), colorMode_(mode), disableSystemAdaptation_(disableSystemAdaptation)
84 {
85 imageFilter_ = RSMaterialFilter::CreateMaterialStyle(static_cast<MATERIAL_BLUR_STYLE>(style), dipScale, ratio);
86 type_ = FilterType::MATERIAL;
87
88 #ifdef USE_M133_SKIA
89 const auto hashFunc = SkChecksum::Hash32;
90 #else
91 const auto hashFunc = SkOpts::hash;
92 #endif
93 hash_ = hashFunc(&type_, sizeof(type_), 0);
94 hash_ = hashFunc(&style, sizeof(style), hash_);
95 hash_ = hashFunc(&colorMode_, sizeof(colorMode_), hash_);
96 hash_ = hashFunc(&ratio, sizeof(ratio), hash_);
97 hash_ = hashFunc(&disableSystemAdaptation_, sizeof(disableSystemAdaptation_), hash_);
98 }
99
RSMaterialFilter(MaterialParam materialParam,BLUR_COLOR_MODE mode)100 RSMaterialFilter::RSMaterialFilter(MaterialParam materialParam, BLUR_COLOR_MODE mode)
101 : RSDrawingFilterOriginal(nullptr), colorMode_(mode),
102 radius_(materialParam.radius), saturation_(materialParam.saturation),
103 brightness_(materialParam.brightness), maskColor_(materialParam.maskColor),
104 disableSystemAdaptation_(materialParam.disableSystemAdaptation)
105 {
106 imageFilter_ = RSMaterialFilter::CreateMaterialFilter(
107 materialParam.radius, materialParam.saturation, materialParam.brightness);
108 type_ = FilterType::MATERIAL;
109 if (colorMode_ == FASTAVERAGE) {
110 colorMode_ = AVERAGE;
111 }
112
113 float radiusForHash = DecreasePrecision(radius_);
114 float saturationForHash = DecreasePrecision(saturation_);
115 float brightnessForHash = DecreasePrecision(brightness_);
116 #ifdef USE_M133_SKIA
117 hash_ = SkChecksum::Hash32(&type_, sizeof(type_), 0);
118 hash_ = SkChecksum::Hash32(&radiusForHash, sizeof(radiusForHash), hash_);
119 hash_ = SkChecksum::Hash32(&saturationForHash, sizeof(saturationForHash), hash_);
120 hash_ = SkChecksum::Hash32(&brightnessForHash, sizeof(brightnessForHash), hash_);
121 hash_ = SkChecksum::Hash32(&maskColor_, sizeof(maskColor_), hash_);
122 hash_ = SkChecksum::Hash32(&colorMode_, sizeof(colorMode_), hash_);
123 hash_ = SkChecksum::Hash32(&disableSystemAdaptation_, sizeof(disableSystemAdaptation_), hash_);
124 #else
125 hash_ = SkOpts::hash(&type_, sizeof(type_), 0);
126 hash_ = SkOpts::hash(&radiusForHash, sizeof(radiusForHash), hash_);
127 hash_ = SkOpts::hash(&saturationForHash, sizeof(saturationForHash), hash_);
128 hash_ = SkOpts::hash(&brightnessForHash, sizeof(brightnessForHash), hash_);
129 hash_ = SkOpts::hash(&maskColor_, sizeof(maskColor_), hash_);
130 hash_ = SkOpts::hash(&colorMode_, sizeof(colorMode_), hash_);
131 hash_ = SkOpts::hash(&disableSystemAdaptation_, sizeof(disableSystemAdaptation_), hash_);
132 #endif
133 }
134
135 RSMaterialFilter::~RSMaterialFilter() = default;
136
RadiusVp2Sigma(float radiusVp,float dipScale)137 float RSMaterialFilter::RadiusVp2Sigma(float radiusVp, float dipScale)
138 {
139 float radiusPx = radiusVp * dipScale;
140 return radiusPx > 0.0f ? BLUR_SIGMA_SCALE * radiusPx + 0.5f : 0.0f;
141 }
142
GetDescription()143 std::string RSMaterialFilter::GetDescription()
144 {
145 return "RSMaterialFilter blur radius is " + std::to_string(radius_) + " sigma";
146 }
147
GetDetailedDescription()148 std::string RSMaterialFilter::GetDetailedDescription()
149 {
150 char maskColorStr[UINT8_MAX] = { 0 };
151 auto ret = memset_s(maskColorStr, UINT8_MAX, 0, UINT8_MAX);
152 if (ret != EOK) {
153 return "Failed to memset_s for maskColorStr, ret=" + std::to_string(ret);
154 }
155 if (sprintf_s(maskColorStr, UINT8_MAX, "%08X", maskColor_.AsArgbInt()) != -1) {
156 return "RSMaterialFilterBlur, radius: " + std::to_string(radius_) + " sigma" +
157 ", saturation: " + std::to_string(saturation_) + ", brightness: " + std::to_string(brightness_) +
158 ", greyCoef1: " + std::to_string(greyCoef_ == std::nullopt ? 0.0f : greyCoef_->x_) +
159 ", greyCoef2: " + std::to_string(greyCoef_ == std::nullopt ? 0.0f : greyCoef_->y_) +
160 ", color: " + maskColorStr + ", colorMode: " + std::to_string(colorMode_);
161 };
162 return "RSMaterialFilterBlur, maskColorStr failed";
163 }
164
Compose(const std::shared_ptr<RSDrawingFilterOriginal> & other) const165 std::shared_ptr<RSDrawingFilterOriginal> RSMaterialFilter::Compose(
166 const std::shared_ptr<RSDrawingFilterOriginal>& other) const
167 {
168 if (other == nullptr) {
169 return nullptr;
170 }
171 MaterialParam materialParam = {radius_, saturation_, brightness_, maskColor_, disableSystemAdaptation_};
172 std::shared_ptr<RSMaterialFilter> result = std::make_shared<RSMaterialFilter>(materialParam, colorMode_);
173 result->imageFilter_ = Drawing::ImageFilter::CreateComposeImageFilter(imageFilter_, other->GetImageFilter());
174 auto otherHash = other->Hash();
175 #ifdef USE_M133_SKIA
176 const auto hashFunc = SkChecksum::Hash32;
177 #else
178 const auto hashFunc = SkOpts::hash;
179 #endif
180 result->hash_ = hashFunc(&otherHash, sizeof(otherHash), hash_);
181 return result;
182 }
183
GetColorFilter(float sat,float brightness)184 std::shared_ptr<Drawing::ColorFilter> RSMaterialFilter::GetColorFilter(float sat, float brightness)
185 {
186 float normalizedDegree = brightness - 1.0;
187 const float brightnessMat[] = {
188 1.000000f, 0.000000f, 0.000000f, 0.000000f, normalizedDegree,
189 0.000000f, 1.000000f, 0.000000f, 0.000000f, normalizedDegree,
190 0.000000f, 0.000000f, 1.000000f, 0.000000f, normalizedDegree,
191 0.000000f, 0.000000f, 0.000000f, 1.000000f, 0.000000f,
192 };
193
194 Drawing::ColorMatrix cm;
195 cm.SetSaturation(sat);
196 float cmArray[Drawing::ColorMatrix::MATRIX_SIZE];
197 cm.GetArray(cmArray);
198 std::shared_ptr<Drawing::ColorFilter> filterCompose =
199 Drawing::ColorFilter::CreateComposeColorFilter(cmArray, brightnessMat);
200 return filterCompose;
201 }
202
CreateMaterialFilter(float radius,float sat,float brightness)203 std::shared_ptr<Drawing::ImageFilter> RSMaterialFilter::CreateMaterialFilter(float radius, float sat, float brightness)
204 {
205 colorFilter_ = GetColorFilter(sat, brightness);
206 auto blurType = KAWASE_BLUR_ENABLED ? Drawing::ImageBlurType::KAWASE : Drawing::ImageBlurType::GAUSS;
207 if (colorFilter_) {
208 return Drawing::ImageFilter::CreateColorBlurImageFilter(*colorFilter_, radius, radius, blurType);
209 }
210 return Drawing::ImageFilter::CreateBlurImageFilter(radius, radius, Drawing::TileMode::CLAMP, nullptr, blurType);
211 }
212
CreateMaterialStyle(MATERIAL_BLUR_STYLE style,float dipScale,float ratio)213 std::shared_ptr<Drawing::ImageFilter> RSMaterialFilter::CreateMaterialStyle(
214 MATERIAL_BLUR_STYLE style, float dipScale, float ratio)
215 {
216 const auto& materialParams = KAWASE_BLUR_ENABLED ? KAWASE_MATERIAL_PARAM : MATERIAL_PARAM;
217 if (auto iter = materialParams.find(style); iter != materialParams.end()) {
218 const auto& materialParam = iter->second;
219 maskColor_ = RSColor(materialParam.maskColor.AsRgbaInt());
220 maskColor_.MultiplyAlpha(ratio);
221 radius_ = RSMaterialFilter::RadiusVp2Sigma(materialParam.radius, dipScale) * ratio;
222 saturation_ = (materialParam.saturation - 1) * ratio + 1.0;
223 brightness_ = (materialParam.brightness - 1) * ratio + 1.0;
224 return RSMaterialFilter::CreateMaterialFilter(radius_, saturation_, brightness_);
225 }
226 return nullptr;
227 }
228
PreProcess(std::shared_ptr<Drawing::Image> imageSnapshot)229 void RSMaterialFilter::PreProcess(std::shared_ptr<Drawing::Image> imageSnapshot)
230 {
231 if (colorMode_ == AVERAGE && imageSnapshot != nullptr) {
232 // update maskColor while persevere alpha
233 auto colorPicker = RSPropertiesPainter::CalcAverageColor(imageSnapshot);
234 maskColor_ = RSColor(Drawing::Color::ColorQuadGetR(colorPicker), Drawing::Color::ColorQuadGetG(colorPicker),
235 Drawing::Color::ColorQuadGetB(colorPicker), maskColor_.GetAlpha());
236 }
237 }
238
PostProcess(Drawing::Canvas & canvas)239 void RSMaterialFilter::PostProcess(Drawing::Canvas& canvas)
240 {
241 Drawing::Brush brush;
242 brush.SetColor(maskColor_.AsArgbInt());
243 canvas.DrawBackground(brush);
244 }
245
TransformFilter(float fraction) const246 std::shared_ptr<RSFilter> RSMaterialFilter::TransformFilter(float fraction) const
247 {
248 MaterialParam materialParam;
249 materialParam.radius = radius_ * fraction;
250 materialParam.saturation = (saturation_ - 1) * fraction + 1.0;
251 materialParam.brightness = (brightness_ - 1) * fraction + 1.0;
252 materialParam.maskColor = RSColor(maskColor_.GetRed(), maskColor_.GetGreen(),
253 maskColor_.GetBlue(), maskColor_.GetAlpha() * fraction);
254 return std::make_shared<RSMaterialFilter>(materialParam, colorMode_);
255 }
256
IsValid() const257 bool RSMaterialFilter::IsValid() const
258 {
259 constexpr float epsilon = 0.999f;
260 return radius_ > epsilon;
261 }
262
NeedForceSubmit() const263 bool RSMaterialFilter::NeedForceSubmit() const
264 {
265 return colorMode_ == AVERAGE;
266 }
267
DrawImageRect(Drawing::Canvas & canvas,const std::shared_ptr<Drawing::Image> & image,const Drawing::Rect & src,const Drawing::Rect & dst) const268 void RSMaterialFilter::DrawImageRect(Drawing::Canvas& canvas, const std::shared_ptr<Drawing::Image>& image,
269 const Drawing::Rect& src, const Drawing::Rect& dst) const
270 {
271 auto brush = GetBrush();
272 // if kawase blur failed, use gauss blur
273 std::shared_ptr<Drawing::Image> greyImage = image;
274 if (greyCoef_.has_value()) {
275 greyImage = RSPropertiesPainter::DrawGreyAdjustment(canvas, image, greyCoef_.value());
276 }
277 if (greyImage == nullptr) {
278 greyImage = image;
279 }
280
281 // if hps blur failed, use kawase blur
282 Drawing::HpsBlurParameter hpsParam = Drawing::HpsBlurParameter(src, dst, GetRadius(), saturation_, brightness_);
283 if (HPS_BLUR_ENABLED &&
284 HpsBlurFilter::GetHpsBlurFilter().ApplyHpsBlur(canvas, greyImage, hpsParam, brush.GetColor().GetAlphaF())) {
285 RS_OPTIONAL_TRACE_NAME("ApplyHPSBlur " + std::to_string(GetRadius()));
286 return;
287 }
288
289 static bool DDGR_ENABLED = RSSystemProperties::GetGpuApiType() == GpuApiType::DDGR;
290 KawaseParameter param = KawaseParameter(src, dst, radius_, colorFilter_, brush.GetColor().GetAlphaF());
291 if (!DDGR_ENABLED && KAWASE_BLUR_ENABLED &&
292 KawaseBlurFilter::GetKawaseBlurFilter()->ApplyKawaseBlur(canvas, greyImage, param)) {
293 return;
294 }
295 canvas.AttachBrush(brush);
296 canvas.DrawImageRect(*greyImage, src, dst, Drawing::SamplingOptions());
297 canvas.DetachBrush();
298 }
299
SetGreyCoef(const std::optional<Vector2f> & greyCoef)300 void RSMaterialFilter::SetGreyCoef(const std::optional<Vector2f>& greyCoef)
301 {
302 greyCoef_ = greyCoef;
303 }
304
GetRadius() const305 float RSMaterialFilter::GetRadius() const
306 {
307 return radius_;
308 }
309
GetSaturation() const310 float RSMaterialFilter::GetSaturation() const
311 {
312 return saturation_;
313 }
314
GetBrightness() const315 float RSMaterialFilter::GetBrightness() const
316 {
317 return brightness_;
318 }
319
GetMaskColor() const320 RSColor RSMaterialFilter::GetMaskColor() const
321 {
322 return maskColor_;
323 }
324
GetColorMode() const325 BLUR_COLOR_MODE RSMaterialFilter::GetColorMode() const
326 {
327 return colorMode_;
328 }
329
GetDisableSystemAdaptation() const330 bool RSMaterialFilter::GetDisableSystemAdaptation() const
331 {
332 return disableSystemAdaptation_;
333 }
334
CanSkipFrame() const335 bool RSMaterialFilter::CanSkipFrame() const
336 {
337 constexpr float HEAVY_BLUR_THRESHOLD = 25.0f;
338 return radius_ > HEAVY_BLUR_THRESHOLD;
339 };
340
341 } // namespace Rosen
342 } // namespace OHOS
343