• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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