• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2025 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 "hpae_base/rs_hpae_fusion_operator.h"
17 #include "hpae_base/rs_hpae_log.h"
18 #include "common/rs_common_def.h"
19 #include "hpae_base/rs_hpae_base_data.h"
20 #include "pipeline/rs_paint_filter_canvas.h"
21 #include "render/rs_render_maskcolor_filter.h"
22 
23 namespace OHOS::Rosen {
24 
25 namespace {
26 std::shared_ptr<Drawing::RuntimeEffect> g_greyShaderEffect_ = nullptr;
27 }
28 
BuildShaderMatrix(Drawing::Matrix & shaderMatrix,const Drawing::Rect & src,const float & greyScaleRatio,const Vector4f & stretchOffset)29 void BuildShaderMatrix(Drawing::Matrix &shaderMatrix, const Drawing::Rect &src, const float &greyScaleRatio,
30     const Vector4f &stretchOffset)
31 {
32     float scaleW = (1.0 - stretchOffset[0] - stretchOffset[2]) * greyScaleRatio;
33     float scaleH = (1.0 - stretchOffset[1] - stretchOffset[3]) * greyScaleRatio;
34 
35     shaderMatrix.PostScale(scaleW, scaleH);
36 
37     Drawing::Matrix translateMatrix;
38     translateMatrix.Translate(
39         stretchOffset[0] * greyScaleRatio * src.GetWidth(), stretchOffset[1] * greyScaleRatio * src.GetHeight());
40     shaderMatrix.PostConcat(translateMatrix);
41 }
42 
MakeGreyShaderEffect()43 static void MakeGreyShaderEffect()
44 {
45     static constexpr char prog[] = R"(
46         uniform shader imageShader;
47         uniform float coefficient1;
48         uniform float coefficient2;
49 
50         float poww(float x, float y) {
51             return (x < 0) ? -pow(-x, y) : pow(x, y);
52         }
53 
54         float calculateT_y(float rgb) {
55             if (rgb > 127.5) { rgb = 255 - rgb; }
56             float b = 38.0;
57             float c = 45.0;
58             float d = 127.5;
59             float A = 106.5;    // 3 * b - 3 * c d;
60             float B = -93;      // 3 * (c - 2 * b);
61             float C = 114;      // 3 * b;
62             float p = 0.816240163988;        // (3 * A * C - pow(B, 2)) / (3 * pow(A, 2));
63             float q = -rgb / 106.5 + 0.262253485943; // -rgb/A - B * C/(3*pow(A, 2)) + 2 * pow(B, 3)/(27*pow(A,3))
64             float s1 = -(q / 2.0);
65             float s2 = sqrt(pow(s1, 2) + pow(p / 3, 3));
66             return poww((s1 + s2), 1.0 / 3) + poww((s1 - s2), 1.0 / 3) - (B / (3 * A));
67         }
68 
69         float calculateGreyAdjustY(float rgb) {
70             float t_r = calculateT_y(rgb);
71             return (rgb < 127.5) ? (rgb + coefficient1 * pow((1 - t_r), 3)) :
72                 (rgb - coefficient2 * pow((1 - t_r), 3));
73         }
74 
75         half4 main(float2 coord) {
76             vec3 color = imageShader.eval(coord).rgb;
77             float Y = (0.299 * color.r + 0.587 * color.g + 0.114 * color.b) * 255;
78             float U = (-0.147 * color.r - 0.289 * color.g + 0.436 * color.b) * 255;
79             float V = (0.615 * color.r - 0.515 * color.g - 0.100 * color.b) * 255;
80             Y = calculateGreyAdjustY(Y);
81             color.r = (Y + 1.14 * V) / 255.0;
82             color.g = (Y - 0.39 * U - 0.58 * V) / 255.0;
83             color.b = (Y + 2.03 * U) / 255.0;
84 
85             return vec4(color, 1.0);
86         }
87     )";
88 
89     if (g_greyShaderEffect_ != nullptr) {
90         return;
91     }
92 
93     g_greyShaderEffect_ = Drawing::RuntimeEffect::CreateForShader(prog);
94 }
95 
MakeGreyShader(float greyLow,float greyHigh,std::shared_ptr<Drawing::ShaderEffect> imageShader)96 std::shared_ptr<Drawing::ShaderEffect> MakeGreyShader(
97     float greyLow, float greyHigh, std::shared_ptr<Drawing::ShaderEffect> imageShader)
98 {
99     // parameter check: near zero
100     constexpr static float EPS = 1e-5f;
101     if (ROSEN_EQ(greyLow, 0.f, EPS) && ROSEN_EQ(greyHigh, 0.f, EPS)) {
102         HPAE_LOGI("MakeGreyShader: grey value is zero");
103         return imageShader;
104     }
105     MakeGreyShaderEffect();
106 
107     if (g_greyShaderEffect_ == nullptr) {
108         HPAE_LOGE("MakeGreyShader: blurEffect create failed!");
109         return imageShader;
110     }
111 
112     std::shared_ptr<Drawing::RuntimeShaderBuilder> builder =
113         std::make_shared<Drawing::RuntimeShaderBuilder>(g_greyShaderEffect_);
114     builder->SetChild("imageShader", imageShader);
115     builder->SetUniform("coefficient1", greyLow);
116     builder->SetUniform("coefficient2", greyHigh);
117     return builder->MakeShader(nullptr, false);
118 }
119 
GetHaePixel(const std::shared_ptr<RSDrawingFilter> & filter)120 HaePixel RSHpaeFusionOperator::GetHaePixel(const std::shared_ptr<RSDrawingFilter> &filter)
121 {
122     HaePixel haePixel;
123     if (filter) {
124         auto maskColorShaderFilter = std::static_pointer_cast<RSMaskColorShaderFilter>(
125             filter->GetShaderFilterWithType(RSUIFilterType::MASK_COLOR));
126         if (maskColorShaderFilter) {
127             RSColor maskColors = maskColorShaderFilter->GetMaskColor();
128             haePixel.a = static_cast<uint16_t>(maskColors.GetAlpha()) * 4;
129             haePixel.r = static_cast<uint16_t>(maskColors.GetRed()) * 4;
130             haePixel.g = static_cast<uint16_t>(maskColors.GetGreen()) * 4;
131             haePixel.b = static_cast<uint16_t>(maskColors.GetBlue()) * 4;
132         }
133     }
134 
135     return haePixel;
136 }
137 
ProcessGreyAndStretch(const Drawing::RectI & clipBounds,const std::shared_ptr<Drawing::Image> & image,const HpaeBufferInfo & targetBuffer,const std::shared_ptr<RSDrawingFilter> & filter,const Drawing::RectI & src)138 int RSHpaeFusionOperator::ProcessGreyAndStretch(const Drawing::RectI& clipBounds,
139     const std::shared_ptr<Drawing::Image> &image, const HpaeBufferInfo &targetBuffer,
140     const std::shared_ptr<RSDrawingFilter> &filter, const Drawing::RectI &src)
141 {
142     auto targetCanvas = targetBuffer.canvas;
143     if (!image || !targetCanvas) {
144         HPAE_LOGE("ProcessGreyAndStretch: input param is null: image: %p, canvas: %p", image.get(), targetCanvas.get());
145         return -1;
146     }
147 
148     float greyScaleRatio = 1.0 * targetCanvas->GetWidth() / src.GetWidth();
149     auto pixelStretch = RSHpaeBaseData::GetInstance().GetPixelStretch();
150     Vector4f stretchOffset(std::abs(pixelStretch.x_) / image->GetWidth(),
151     std::abs(pixelStretch.y_) / image->GetHeight(),
152     std::abs(pixelStretch.z_) / image->GetWidth(),
153     std::abs(pixelStretch.w_) / image->GetHeight());
154     Drawing::Matrix shaderMatrix;
155     BuildShaderMatrix(shaderMatrix, src, greyScaleRatio, stretchOffset);
156 
157     auto tileMode = static_cast<Drawing::TileMode>(RSHpaeBaseData::GetInstance().GetTileMode());
158     HPAE_TRACE_NAME_FMT("ProcessGreyAndStretch. offset:[%f, %f, %f, %f], tileMode:%d, image:[%dx%d]",
159         pixelStretch.x_, pixelStretch.y_, pixelStretch.z_, pixelStretch.w_, tileMode,
160         image->GetWidth(), image->GetHeight());
161     auto imageShader = Drawing::ShaderEffect::CreateImageShader(
162         *image, tileMode, tileMode, Drawing::SamplingOptions(Drawing::FilterMode::LINEAR), shaderMatrix);
163     auto greyCoef = RSHpaeBaseData::GetInstance().GetGreyCoef();
164     auto shader = MakeGreyShader(greyCoef.x_, greyCoef.y_, imageShader);
165     if (shader == nullptr) {
166         HPAE_LOGE("ProcessGreyAndStretch: shader is null!");
167         return -1;
168     }
169 
170     Drawing::Brush brush;
171     brush.SetShaderEffect(shader);
172     Drawing::AutoCanvasRestore acr(*targetCanvas, true);
173     targetCanvas->ResetMatrix();
174     targetCanvas->DrawBackground(brush);
175 
176     return 0;
177 }
178 
GetColorMatrixCoef(const std::shared_ptr<RSDrawingFilter> & filter,float (& colorMatrix)[HAE_COLOR_MATRIX_COEF_COUNT])179 void RSHpaeFusionOperator::GetColorMatrixCoef(const std::shared_ptr<RSDrawingFilter>& filter,
180     float (&colorMatrix)[HAE_COLOR_MATRIX_COEF_COUNT])
181 {
182     float brightnessForHpae = RSHpaeBaseData::GetInstance().GetBrightness();
183     float saturationForHpae = RSHpaeBaseData::GetInstance().GetSaturation();
184     float normalizedDegree = brightnessForHpae - 1.0;
185     Drawing::ColorMatrix cm;
186     cm.SetSaturation(saturationForHpae);
187     cm.GetArray(colorMatrix);
188     colorMatrix[Drawing::ColorMatrix::TRANS_FOR_R] += normalizedDegree;
189     colorMatrix[Drawing::ColorMatrix::TRANS_FOR_G] += normalizedDegree;
190     colorMatrix[Drawing::ColorMatrix::TRANS_FOR_B] += normalizedDegree;
191 }
192 
GetShaderTransform(const Drawing::Rect & blurRect,float scaleW,float scaleH)193 Drawing::Matrix RSHpaeFusionOperator::GetShaderTransform(const Drawing::Rect& blurRect, float scaleW, float scaleH)
194 {
195     Drawing::Matrix matrix;
196     matrix.SetScale(scaleW, scaleH);
197     Drawing::Matrix translateMatrix;
198     translateMatrix.Translate(blurRect.GetLeft(), blurRect.GetTop());
199     matrix.PostConcat(translateMatrix);
200     return matrix;
201 }
202 } // OHOS::Rosen