1 /*
2 * Copyright (c) 2021-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 "effect/shader_effect.h"
17 #include "effect/shader_effect_lazy.h"
18 #include "utils/log.h"
19
20 #include "impl_factory.h"
21
22 #ifdef ROSEN_OHOS
23 #include "utils/object_helper.h"
24 #endif
25
26 namespace OHOS {
27 namespace Rosen {
28 namespace Drawing {
29 /* ColorShader */
ShaderEffect(ShaderEffectType t,ColorQuad color)30 ShaderEffect::ShaderEffect(ShaderEffectType t, ColorQuad color) noexcept : ShaderEffect(t)
31 {
32 impl_->InitWithColor(color);
33 }
34
35 /* ColorShader With ColorSpace */
ShaderEffect(ShaderEffectType t,const Color4f & color,std::shared_ptr<ColorSpace> colorSpace)36 ShaderEffect::ShaderEffect(ShaderEffectType t, const Color4f& color, std::shared_ptr<ColorSpace> colorSpace) noexcept
37 : ShaderEffect(t)
38 {
39 impl_->InitWithColorSpace(color, colorSpace);
40 }
41
42 /* BlendShader */
ShaderEffect(ShaderEffectType t,ShaderEffect & dst,ShaderEffect & src,BlendMode mode)43 ShaderEffect::ShaderEffect(ShaderEffectType t, ShaderEffect& dst, ShaderEffect& src, BlendMode mode) noexcept
44 : ShaderEffect(t)
45 {
46 impl_->InitWithBlend(dst, src, mode);
47 }
48
49 /* ImageShader */
ShaderEffect(ShaderEffectType t,const Image & image,TileMode tileX,TileMode tileY,const SamplingOptions & sampling,const Matrix & matrix)50 ShaderEffect::ShaderEffect(ShaderEffectType t, const Image& image, TileMode tileX, TileMode tileY,
51 const SamplingOptions& sampling, const Matrix& matrix) noexcept
52 : ShaderEffect(t)
53 {
54 impl_->InitWithImage(image, tileX, tileY, sampling, matrix);
55 }
56
57 /* PictureShader */
ShaderEffect(ShaderEffectType t,const Picture & picture,TileMode tileX,TileMode tileY,FilterMode mode,const Matrix & matrix,const Rect & rect)58 ShaderEffect::ShaderEffect(ShaderEffectType t, const Picture& picture, TileMode tileX, TileMode tileY, FilterMode mode,
59 const Matrix& matrix, const Rect& rect) noexcept
60 : ShaderEffect(t)
61 {
62 impl_->InitWithPicture(picture, tileX, tileY, mode, matrix, rect);
63 }
64
65 /* LinearGradient */
ShaderEffect(ShaderEffectType t,const Point & startPt,const Point & endPt,const std::vector<ColorQuad> & colors,const std::vector<scalar> & pos,TileMode mode,const Matrix * matrix)66 ShaderEffect::ShaderEffect(ShaderEffectType t, const Point& startPt, const Point& endPt,
67 const std::vector<ColorQuad>& colors, const std::vector<scalar>& pos, TileMode mode, const Matrix *matrix) noexcept
68 : ShaderEffect(t)
69 {
70 impl_->InitWithLinearGradient(startPt, endPt, colors, pos, mode, matrix);
71 }
72
73 /* LinearGradient */
ShaderEffect(ShaderEffectType t,const Point & startPt,const Point & endPt,const std::vector<Color4f> & colors,std::shared_ptr<ColorSpace> colorSpace,const std::vector<scalar> & pos,TileMode mode,const Matrix * matrix)74 ShaderEffect::ShaderEffect(ShaderEffectType t, const Point& startPt, const Point& endPt,
75 const std::vector<Color4f>& colors, std::shared_ptr<ColorSpace> colorSpace, const std::vector<scalar>& pos,
76 TileMode mode, const Matrix *matrix) noexcept
77 : ShaderEffect(t)
78 {
79 impl_->InitWithLinearGradient(startPt, endPt, colors, colorSpace, pos, mode, matrix);
80 }
81
82 /* RadialGradient */
ShaderEffect(ShaderEffectType t,const Point & centerPt,scalar radius,const std::vector<ColorQuad> & colors,const std::vector<scalar> & pos,TileMode mode,const Matrix * matrix)83 ShaderEffect::ShaderEffect(ShaderEffectType t, const Point& centerPt, scalar radius,
84 const std::vector<ColorQuad>& colors, const std::vector<scalar>& pos, TileMode mode, const Matrix *matrix) noexcept
85 : ShaderEffect(t)
86 {
87 impl_->InitWithRadialGradient(centerPt, radius, colors, pos, mode, matrix);
88 }
89
90 /* RadialGradient */
ShaderEffect(ShaderEffectType t,const Point & centerPt,scalar radius,const std::vector<Color4f> & colors,std::shared_ptr<ColorSpace> colorSpace,const std::vector<scalar> & pos,TileMode mode,const Matrix * matrix)91 ShaderEffect::ShaderEffect(ShaderEffectType t, const Point& centerPt, scalar radius,
92 const std::vector<Color4f>& colors, std::shared_ptr<ColorSpace> colorSpace, const std::vector<scalar>& pos,
93 TileMode mode, const Matrix* matrix) noexcept
94 : ShaderEffect(t)
95 {
96 impl_->InitWithRadialGradient(centerPt, radius, colors, colorSpace, pos, mode, matrix);
97 }
98
99 /* TwoPointConicalGradient */
ShaderEffect(ShaderEffectType t,const Point & startPt,scalar startRadius,const Point & endPt,scalar endRadius,const std::vector<ColorQuad> & colors,const std::vector<scalar> & pos,TileMode mode,const Matrix * matrix)100 ShaderEffect::ShaderEffect(ShaderEffectType t, const Point& startPt, scalar startRadius, const Point& endPt,
101 scalar endRadius, const std::vector<ColorQuad>& colors, const std::vector<scalar>& pos, TileMode mode,
102 const Matrix *matrix) noexcept
103 : ShaderEffect(t)
104 {
105 impl_->InitWithTwoPointConical(startPt, startRadius, endPt, endRadius, colors, pos, mode, matrix);
106 }
107
108 /* TwoPointConicalGradient */
ShaderEffect(ShaderEffectType t,const Point & startPt,scalar startRadius,const Point & endPt,scalar endRadius,const std::vector<Color4f> & colors,std::shared_ptr<ColorSpace> colorSpace,const std::vector<scalar> & pos,TileMode mode,const Matrix * matrix)109 ShaderEffect::ShaderEffect(ShaderEffectType t, const Point& startPt, scalar startRadius, const Point& endPt,
110 scalar endRadius, const std::vector<Color4f>& colors, std::shared_ptr<ColorSpace> colorSpace,
111 const std::vector<scalar>& pos, TileMode mode, const Matrix* matrix) noexcept
112 : ShaderEffect(t)
113 {
114 impl_->InitWithTwoPointConical(startPt, startRadius, endPt, endRadius, colors, colorSpace, pos, mode, matrix);
115 }
116
117 /* SweepGradient */
ShaderEffect(ShaderEffectType t,const Point & centerPt,const std::vector<ColorQuad> & colors,const std::vector<scalar> & pos,TileMode mode,scalar startAngle,scalar endAngle,const Matrix * matrix)118 ShaderEffect::ShaderEffect(ShaderEffectType t, const Point& centerPt, const std::vector<ColorQuad>& colors,
119 const std::vector<scalar>& pos, TileMode mode, scalar startAngle, scalar endAngle, const Matrix *matrix) noexcept
120 : ShaderEffect(t)
121 {
122 impl_->InitWithSweepGradient(centerPt, colors, pos, mode, startAngle, endAngle, matrix);
123 }
124
125 /* SweepGradient */
ShaderEffect(ShaderEffectType t,const Point & centerPt,const std::vector<Color4f> & colors,std::shared_ptr<ColorSpace> colorSpace,const std::vector<scalar> & pos,TileMode mode,scalar startAngle,scalar endAngle,const Matrix * matrix)126 ShaderEffect::ShaderEffect(ShaderEffectType t, const Point& centerPt, const std::vector<Color4f>& colors,
127 std::shared_ptr<ColorSpace> colorSpace, const std::vector<scalar>& pos, TileMode mode, scalar startAngle,
128 scalar endAngle, const Matrix* matrix) noexcept
129 : ShaderEffect(t)
130 {
131 impl_->InitWithSweepGradient(centerPt, colors, colorSpace, pos, mode, startAngle, endAngle, matrix);
132 }
133
134 /* ExtendShader */
ShaderEffect(ShaderEffectType t,std::shared_ptr<ExtendObject> object)135 ShaderEffect::ShaderEffect(ShaderEffectType t, std::shared_ptr<ExtendObject> object) noexcept
136 : type_(t), impl_(ImplFactory::CreateShaderEffectImpl()), object_(object) {}
137
138 /* SdfShader */
ShaderEffect(ShaderEffectType t,const SDFShapeBase & shape)139 ShaderEffect::ShaderEffect(ShaderEffectType t, const SDFShapeBase& shape) noexcept
140 : ShaderEffect(t)
141 {
142 impl_->InitWithSdf(shape);
143 }
144
ShaderEffect()145 ShaderEffect::ShaderEffect() noexcept
146 : type_(ShaderEffect::ShaderEffectType::NO_TYPE), impl_(ImplFactory::CreateShaderEffectImpl())
147 {}
148
ShaderEffect(ShaderEffectType t)149 ShaderEffect::ShaderEffect(ShaderEffectType t) noexcept : type_(t), impl_(ImplFactory::CreateShaderEffectImpl()) {}
150
GetType() const151 ShaderEffect::ShaderEffectType ShaderEffect::GetType() const
152 {
153 return type_;
154 }
155
CreateColorShader(ColorQuad color)156 std::shared_ptr<ShaderEffect> ShaderEffect::CreateColorShader(ColorQuad color)
157 {
158 return std::make_shared<ShaderEffect>(ShaderEffect::ShaderEffectType::COLOR_SHADER, color);
159 }
160
CreateColorSpaceShader(const Color4f & color,std::shared_ptr<ColorSpace> colorSpace)161 std::shared_ptr<ShaderEffect> ShaderEffect::CreateColorSpaceShader(const Color4f& color,
162 std::shared_ptr<ColorSpace> colorSpace)
163 {
164 return std::make_shared<ShaderEffect>(ShaderEffect::ShaderEffectType::COLOR_SHADER, color, colorSpace);
165 }
166
CreateBlendShader(ShaderEffect & dst,ShaderEffect & src,BlendMode mode)167 std::shared_ptr<ShaderEffect> ShaderEffect::CreateBlendShader(ShaderEffect& dst, ShaderEffect& src, BlendMode mode)
168 {
169 // Check if dst shader is Lazy type, not supported for direct CreateBlendShader
170 if (dst.IsLazy()) {
171 LOGE("ShaderEffect::CreateBlendShader, dst shader is Lazy type, not supported.");
172 return nullptr;
173 }
174
175 // Check if src shader is Lazy type, not supported for direct CreateBlendShader
176 if (src.IsLazy()) {
177 LOGE("ShaderEffect::CreateBlendShader, src shader is Lazy type, not supported.");
178 return nullptr;
179 }
180
181 return std::make_shared<ShaderEffect>(ShaderEffect::ShaderEffectType::BLEND, dst, src, mode);
182 }
183
CreateImageShader(const Image & image,TileMode tileX,TileMode tileY,const SamplingOptions & sampling,const Matrix & matrix)184 std::shared_ptr<ShaderEffect> ShaderEffect::CreateImageShader(
185 const Image& image, TileMode tileX, TileMode tileY, const SamplingOptions& sampling, const Matrix& matrix)
186 {
187 return std::make_shared<ShaderEffect>(ShaderEffect::ShaderEffectType::IMAGE, image, tileX, tileY, sampling, matrix);
188 }
189
CreatePictureShader(const Picture & picture,TileMode tileX,TileMode tileY,FilterMode mode,const Matrix & matrix,const Rect & rect)190 std::shared_ptr<ShaderEffect> ShaderEffect::CreatePictureShader(
191 const Picture& picture, TileMode tileX, TileMode tileY, FilterMode mode, const Matrix& matrix, const Rect& rect)
192 {
193 return std::make_shared<ShaderEffect>(
194 ShaderEffect::ShaderEffectType::PICTURE, picture, tileX, tileY, mode, matrix, rect);
195 }
196
CreateLinearGradient(const Point & startPt,const Point & endPt,const std::vector<ColorQuad> & colors,const std::vector<scalar> & pos,TileMode mode,const Matrix * matrix)197 std::shared_ptr<ShaderEffect> ShaderEffect::CreateLinearGradient(const Point& startPt, const Point& endPt,
198 const std::vector<ColorQuad>& colors, const std::vector<scalar>& pos, TileMode mode, const Matrix *matrix)
199 {
200 return std::make_shared<ShaderEffect>(
201 ShaderEffect::ShaderEffectType::LINEAR_GRADIENT, startPt, endPt, colors, pos, mode, matrix);
202 }
203
CreateLinearGradient(const Point & startPt,const Point & endPt,const std::vector<Color4f> & colors,std::shared_ptr<ColorSpace> colorSpace,const std::vector<scalar> & pos,TileMode mode,const Matrix * matrix)204 std::shared_ptr<ShaderEffect> ShaderEffect::CreateLinearGradient(const Point& startPt, const Point& endPt,
205 const std::vector<Color4f>& colors, std::shared_ptr<ColorSpace> colorSpace, const std::vector<scalar>& pos,
206 TileMode mode, const Matrix *matrix)
207 {
208 return std::make_shared<ShaderEffect>(
209 ShaderEffect::ShaderEffectType::LINEAR_GRADIENT, startPt, endPt, colors, colorSpace, pos, mode, matrix);
210 }
211
CreateRadialGradient(const Point & centerPt,scalar radius,const std::vector<ColorQuad> & colors,const std::vector<scalar> & pos,TileMode mode,const Matrix * matrix)212 std::shared_ptr<ShaderEffect> ShaderEffect::CreateRadialGradient(const Point& centerPt, scalar radius,
213 const std::vector<ColorQuad>& colors, const std::vector<scalar>& pos, TileMode mode, const Matrix *matrix)
214 {
215 return std::make_shared<ShaderEffect>(
216 ShaderEffect::ShaderEffectType::RADIAL_GRADIENT, centerPt, radius, colors, pos, mode, matrix);
217 }
218
CreateRadialGradient(const Point & centerPt,scalar radius,const std::vector<Color4f> & colors,std::shared_ptr<ColorSpace> colorSpace,const std::vector<scalar> & pos,TileMode mode,const Matrix * matrix)219 std::shared_ptr<ShaderEffect> ShaderEffect::CreateRadialGradient(const Point& centerPt, scalar radius,
220 const std::vector<Color4f>& colors, std::shared_ptr<ColorSpace> colorSpace, const std::vector<scalar>& pos,
221 TileMode mode, const Matrix* matrix)
222 {
223 return std::make_shared<ShaderEffect>(
224 ShaderEffect::ShaderEffectType::RADIAL_GRADIENT, centerPt, radius, colors, colorSpace, pos, mode, matrix);
225 }
226
CreateTwoPointConical(const Point & startPt,scalar startRadius,const Point & endPt,scalar endRadius,const std::vector<ColorQuad> & colors,const std::vector<scalar> & pos,TileMode mode,const Matrix * matrix)227 std::shared_ptr<ShaderEffect> ShaderEffect::CreateTwoPointConical(const Point& startPt, scalar startRadius,
228 const Point& endPt, scalar endRadius, const std::vector<ColorQuad>& colors, const std::vector<scalar>& pos,
229 TileMode mode, const Matrix *matrix)
230 {
231 return std::make_shared<ShaderEffect>(
232 ShaderEffect::ShaderEffectType::CONICAL_GRADIENT, startPt, startRadius, endPt, endRadius, colors, pos, mode,
233 matrix);
234 }
235
CreateTwoPointConical(const Point & startPt,scalar startRadius,const Point & endPt,scalar endRadius,const std::vector<Color4f> & colors,std::shared_ptr<ColorSpace> colorSpace,const std::vector<scalar> & pos,TileMode mode,const Matrix * matrix)236 std::shared_ptr<ShaderEffect> ShaderEffect::CreateTwoPointConical(const Point& startPt, scalar startRadius,
237 const Point& endPt, scalar endRadius, const std::vector<Color4f>& colors, std::shared_ptr<ColorSpace> colorSpace,
238 const std::vector<scalar>& pos, TileMode mode, const Matrix *matrix)
239 {
240 return std::make_shared<ShaderEffect>(
241 ShaderEffect::ShaderEffectType::CONICAL_GRADIENT, startPt, startRadius, endPt, endRadius, colors, colorSpace,
242 pos, mode, matrix);
243 }
244
CreateSweepGradient(const Point & centerPt,const std::vector<ColorQuad> & colors,const std::vector<scalar> & pos,TileMode mode,scalar startAngle,scalar endAngle,const Matrix * matrix)245 std::shared_ptr<ShaderEffect> ShaderEffect::CreateSweepGradient(const Point& centerPt,
246 const std::vector<ColorQuad>& colors, const std::vector<scalar>& pos, TileMode mode, scalar startAngle,
247 scalar endAngle, const Matrix *matrix)
248 {
249 return std::make_shared<ShaderEffect>(
250 ShaderEffect::ShaderEffectType::SWEEP_GRADIENT, centerPt, colors, pos, mode, startAngle, endAngle, matrix);
251 }
252
CreateSweepGradient(const Point & centerPt,const std::vector<Color4f> & colors,std::shared_ptr<ColorSpace> colorSpace,const std::vector<scalar> & pos,TileMode mode,scalar startAngle,scalar endAngle,const Matrix * matrix)253 std::shared_ptr<ShaderEffect> ShaderEffect::CreateSweepGradient(const Point& centerPt,
254 const std::vector<Color4f>& colors, std::shared_ptr<ColorSpace> colorSpace,const std::vector<scalar>& pos,
255 TileMode mode, scalar startAngle, scalar endAngle, const Matrix* matrix)
256 {
257 return std::make_shared<ShaderEffect>(
258 ShaderEffect::ShaderEffectType::SWEEP_GRADIENT, centerPt, colors, colorSpace, pos, mode, startAngle,
259 endAngle, matrix);
260 }
261
CreateExtendShader(std::shared_ptr<ExtendObject> object)262 std::shared_ptr<ShaderEffect> ShaderEffect::CreateExtendShader(std::shared_ptr<ExtendObject> object)
263 {
264 return std::make_shared<ShaderEffect>(ShaderEffect::ShaderEffectType::EXTEND_SHADER, object);
265 }
266
CreateSdfShader(const SDFShapeBase & shape)267 std::shared_ptr<ShaderEffect> ShaderEffect::CreateSdfShader(const SDFShapeBase& shape)
268 {
269 return std::make_shared<ShaderEffect>(ShaderEffect::ShaderEffectType::SDF_SHADER, shape);
270 }
271
272 #ifdef RS_ENABLE_GPU
SetGPUContext(std::shared_ptr<GPUContext> gpuContext) const273 void ShaderEffect::SetGPUContext(std::shared_ptr<GPUContext> gpuContext) const
274 {
275 impl_->SetGPUContext(gpuContext);
276 }
277 #endif
278
Serialize() const279 std::shared_ptr<Data> ShaderEffect::Serialize() const
280 {
281 return impl_->Serialize();
282 }
283
Deserialize(std::shared_ptr<Data> data)284 bool ShaderEffect::Deserialize(std::shared_ptr<Data> data)
285 {
286 return impl_->Deserialize(data);
287 }
288
289 #ifdef ROSEN_OHOS
Marshalling(Parcel & parcel)290 bool ShaderEffect::Marshalling(Parcel& parcel)
291 {
292 // Write type first
293 if (!parcel.WriteInt32(static_cast<int32_t>(type_))) {
294 LOGE("ShaderEffect::Marshalling, failed to write type");
295 return false;
296 }
297
298 // Use Serialize to convert to Data then serialize
299 auto data = Serialize();
300
301 // Write flag indicating whether data is valid
302 bool hasValidData = (data != nullptr && data->GetSize() > 0);
303 if (!parcel.WriteBool(hasValidData)) {
304 LOGE("ShaderEffect::Marshalling, failed to write hasData flag");
305 return false;
306 }
307
308 // If data is null or empty (empty shader), just write the flag and return success
309 // This prevents parcel failure when underlying shader creation failed
310 if (!hasValidData) {
311 LOGD("ShaderEffect::Marshalling, Serialize returned null or empty data (empty shader), "
312 "continuing with empty marker");
313 return true;
314 }
315
316 // Use registered callback for Data marshalling
317 auto callback = ObjectHelper::Instance().GetDataMarshallingCallback();
318 if (!callback) {
319 LOGE("ShaderEffect::Marshalling, DataMarshallingCallback is not registered");
320 return false;
321 }
322 if (!callback(parcel, data)) {
323 LOGE("ShaderEffect::Marshalling, DataMarshallingCallback failed");
324 return false;
325 }
326 return true;
327 }
328
Unmarshalling(Parcel & parcel,bool & isValid)329 std::shared_ptr<ShaderEffect> ShaderEffect::Unmarshalling(Parcel& parcel, bool& isValid)
330 {
331 // Read type first
332 int32_t typeValue;
333 if (!parcel.ReadInt32(typeValue)) {
334 LOGE("ShaderEffect::Unmarshalling, failed to read type");
335 return nullptr;
336 }
337
338 // Validate type range (should be valid shader types, excluding NO_TYPE and LAZY_SHADER)
339 if (typeValue < static_cast<int32_t>(ShaderEffectType::NO_TYPE) ||
340 typeValue >= static_cast<int32_t>(ShaderEffectType::LAZY_SHADER)) {
341 LOGE("ShaderEffect::Unmarshalling, invalid type value: %{public}d", typeValue);
342 return nullptr;
343 }
344
345 // Read hasData flag
346 bool hasData;
347 if (!parcel.ReadBool(hasData)) {
348 LOGE("ShaderEffect::Unmarshalling, failed to read hasData flag");
349 return nullptr;
350 }
351
352 // If no data (empty shader), create an empty ShaderEffect and return
353 if (!hasData) {
354 LOGD("ShaderEffect::Unmarshalling, empty shader marker detected, creating empty ShaderEffect");
355 auto shader = std::make_shared<ShaderEffect>(static_cast<ShaderEffectType>(typeValue));
356 return shader;
357 }
358
359 // Use registered callback for Data unmarshalling
360 auto callback = ObjectHelper::Instance().GetDataUnmarshallingCallback();
361 if (!callback) {
362 LOGE("ShaderEffect::Unmarshalling, DataUnmarshallingCallback is not registered");
363 return nullptr;
364 }
365 auto data = callback(parcel);
366 if (!data) {
367 LOGE("ShaderEffect::Unmarshalling, DataUnmarshallingCallback failed");
368 return nullptr;
369 }
370
371 // Create ShaderEffect with correct type
372 auto shader = std::make_shared<ShaderEffect>(static_cast<ShaderEffectType>(typeValue));
373 if (!shader->Deserialize(data)) {
374 LOGE("ShaderEffect::Unmarshalling, Deserialize failed");
375 // For compatibility: mark as invalid but return object instead of nullptr
376 isValid = false;
377 return shader;
378 }
379 return shader;
380 }
381 #endif
382 } // namespace Drawing
383 } // namespace Rosen
384 } // namespace OHOS
385