• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "src/core/SkSDFFilter.h"
17 #include "src/gpu/SkGr.h"
18 #include "src/gpu/effects/GrBlendFragmentProcessor.h"
19 
20 #ifdef SK_ENABLE_SDF_BLUR_SWITCH
21 #include <parameters.h>
22 #endif
23 
24 namespace SDFBlur {
25 
GetSDFBlurEnabled()26 static bool GetSDFBlurEnabled()
27 {
28 #ifdef SK_ENABLE_SDF_BLUR_SWITCH
29     constexpr int enableFlag = 1;
30     static bool enabled = std::atoi(
31         (OHOS::system::GetParameter("persist.sys.graphic.SDFBlurEnabled", "1")).c_str()) == enableFlag;
32     return enabled;
33 #else
34     return false;
35 #endif
36 }
37 
GetSDFBlurDebugTraceEnabled()38 bool GetSDFBlurDebugTraceEnabled()
39 {
40 #ifdef SK_ENABLE_SDF_BLUR_SWITCH
41     constexpr int enableFlag = 1;
42     static bool enabled = std::atoi(
43         (OHOS::system::GetParameter("persist.sys.graphic.SDFBlurDebugTraceEnabled", "0")).c_str()) == enableFlag;
44     return enabled;
45 #else
46     return false;
47 #endif
48 }
49 
50 // Only the equal Radii RRect use SDFblur.
isSDFBlur(const GrStyledShape & shape)51 bool isSDFBlur(const GrStyledShape& shape)
52 {
53     SkRRect srcRRect;
54     bool inverted;
55     if (!GetSDFBlurEnabled() || !shape.asRRect(&srcRRect, nullptr, nullptr, &inverted) || inverted ||
56         (!(srcRRect.getType() == SkRRect::kSimple_Type) && !(srcRRect.getType() == SkRRect::kNinePatch_Type))) {
57         return false;
58     }
59     return true;
60 }
61 
GetSDFBlurScaleFactor(const SkRRect srcRRect,const SkMatrix & viewMatrix,SkScalar & sx,SkScalar & sy)62 void GetSDFBlurScaleFactor(const SkRRect srcRRect, const SkMatrix& viewMatrix, SkScalar& sx, SkScalar& sy)
63 {
64     if (viewMatrix.getScaleX() >= 1.f || viewMatrix.getScaleY() >= 1.f) {
65         return;
66     }
67     constexpr float minScaleFactor = 1.f;
68     constexpr float maxScaleFactor = 2.f;
69     constexpr float sizeThreshold = 500.f;
70     int srcRRectW = srcRRect.rect().width();
71     int srcRRectH = srcRRect.rect().height();
72     // When the input size is greater than the threshold, it needs to be scaled.
73     // scale factor will be clamped in [1.0, 2.0].
74     int scaleX = std::max(minScaleFactor, std::min(std::ceil(srcRRectW / sizeThreshold), maxScaleFactor));
75     int scaleY = std::max(minScaleFactor, std::min(std::ceil(srcRRectH / sizeThreshold), maxScaleFactor));
76     sx = SK_Scalar1 / scaleX;
77     sy = SK_Scalar1 / scaleY;
78 }
79 
drawMaskSDFBlur(GrRecordingContext * rContext,skgpu::v1::SurfaceDrawContext * sdc,const GrClip * clip,const SkMatrix & viewMatrix,const SkIRect & maskBounds,GrPaint && paint,GrSurfaceProxyView mask,const SkMaskFilterBase * maskFilter,const SkScalar sx,const SkScalar sy)80 bool drawMaskSDFBlur(GrRecordingContext* rContext, skgpu::v1::SurfaceDrawContext* sdc, const GrClip* clip,
81     const SkMatrix& viewMatrix, const SkIRect& maskBounds, GrPaint&& paint, GrSurfaceProxyView mask,
82     const SkMaskFilterBase* maskFilter, const SkScalar sx, const SkScalar sy)
83 {
84     float noxFormedSigma3 = maskFilter->getNoxFormedSigma3();
85     mask.concatSwizzle(GrSwizzle("aaaa"));
86 
87     SkMatrix matrixTrans =
88             SkMatrix::Translate(-SkIntToScalar(noxFormedSigma3), -SkIntToScalar(noxFormedSigma3));
89     SkMatrix matrixInverseScale = SkMatrix::Scale(1 / sx, 1 / sy);
90     SkMatrix matrix;
91     matrix.preConcat(viewMatrix);
92     matrix.preConcat(matrixTrans);
93     matrix.preConcat(matrixInverseScale);
94     // add dither effect to reduce color discontinuity
95     constexpr float ditherRange = 1.f / 255.f;
96     auto inputFp = GrTextureEffect::Make(std::move(mask), kUnknown_SkAlphaType);
97     SkPMColor4f origColor = paint.getColor4f();
98 
99     static auto effect = SkMakeRuntimeEffect(SkRuntimeEffect::MakeForShader, R"(
100         uniform shader fp;
101         uniform half4 colorPaint;
102         half4 main(float2 pos) {
103 
104             half4 colorMask = fp.eval(pos);
105             return colorMask * colorPaint;
106         }
107     )");
108     SkASSERT(SkRuntimeEffectPriv::SupportsConstantOutputForConstantInput(effect));
109     auto inputFP = GrSkSLFP::Make(effect, "OverrideInput", nullptr,
110         origColor.isOpaque() ? GrSkSLFP::OptFlags::kPreservesOpaqueInput : GrSkSLFP::OptFlags::kNone,
111         "fp", std::move(inputFp), "colorPaint", origColor);
112 
113     auto paintFP = GrBlendFragmentProcessor::Make(std::move(inputFP), nullptr, SkBlendMode::kSrc);
114 
115     #ifndef SK_IGNORE_GPU_DITHER
116     paintFP = make_dither_effect(rContext, std::move(paintFP), ditherRange, rContext->priv().caps());
117     #endif
118     paint.setColorFragmentProcessor(std::move(paintFP));
119     sdc->drawRect(clip, std::move(paint), GrAA::kYes, matrix,
120                   SkRect::MakeXYWH(0, 0, maskBounds.width(), maskBounds.height()));
121     return true;
122 }
123 
sdf_2d(GrRecordingContext * rContext,GrSurfaceProxyView srcView,GrColorType srcColorType,const SkIRect & srcBounds,const SkIRect & dstBounds,float noxFormedSigma,SkTileMode mode,sk_sp<SkColorSpace> finalCS,SkBackingFit dstFit,const SkMatrix & viewMatrix,const SkRRect & srcRRect)124 static std::unique_ptr<skgpu::v1::SurfaceDrawContext> sdf_2d(GrRecordingContext* rContext,
125     GrSurfaceProxyView srcView, GrColorType srcColorType, const SkIRect& srcBounds, const SkIRect& dstBounds,
126     float noxFormedSigma, SkTileMode mode, sk_sp<SkColorSpace> finalCS, SkBackingFit dstFit,
127     const SkMatrix& viewMatrix, const SkRRect& srcRRect)
128 {
129     auto sdc = skgpu::v1::SurfaceDrawContext::Make(
130         rContext, srcColorType, std::move(finalCS), dstFit, dstBounds.size(), SkSurfaceProps(),
131         1, GrMipmapped::kNo, srcView.proxy()->isProtected(), srcView.origin());
132     if (!sdc) {
133         return nullptr;
134     }
135 
136     GrPaint paint;
137     auto sdfFp = GrSDFBlurEffect::Make(rContext, noxFormedSigma, srcRRect);
138     if (!sdfFp) {
139         return nullptr;
140     }
141 
142     paint.setColorFragmentProcessor(std::move(sdfFp));
143     paint.setPorterDuffXPFactory(SkBlendMode::kSrc);
144 
145     SkScalar sx = viewMatrix.getScaleX();
146     SkScalar sy = viewMatrix.getScaleY();
147     sdc->drawPaint(nullptr, std::move(paint), SkMatrix::I().Scale(sx, sy));
148 
149     return sdc;
150 }
151 
SDFBlur(GrRecordingContext * rContext,GrSurfaceProxyView srcView,GrColorType srcColorType,SkAlphaType srcAlphaType,sk_sp<SkColorSpace> colorSpace,SkIRect dstBounds,SkIRect srcBounds,float noxFormedSigma,SkTileMode mode,const SkMatrix & viewMatrix,const SkRRect & srcRRect,SkBackingFit fit)152 std::unique_ptr<skgpu::v1::SurfaceDrawContext> SDFBlur(GrRecordingContext* rContext,
153     GrSurfaceProxyView srcView, GrColorType srcColorType, SkAlphaType srcAlphaType,
154     sk_sp<SkColorSpace> colorSpace, SkIRect dstBounds, SkIRect srcBounds, float noxFormedSigma,
155     SkTileMode mode, const SkMatrix& viewMatrix, const SkRRect& srcRRect, SkBackingFit fit)
156 {
157     SkASSERT(rContext);
158     TRACE_EVENT0("skia.gpu", "SDFBlur");
159 
160     if (!srcView.asTextureProxy()) {
161         return nullptr;
162     }
163 
164     int maxRenderTargetSize = rContext->priv().caps()->maxRenderTargetSize();
165     if (dstBounds.width() > maxRenderTargetSize || dstBounds.height() > maxRenderTargetSize) {
166         return nullptr;
167     }
168 
169     return sdf_2d(rContext, std::move(srcView), srcColorType, srcBounds, dstBounds, noxFormedSigma, mode,
170                   std::move(colorSpace), fit, viewMatrix, srcRRect);
171 }
172 } // SDFBlur
173