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