xref: /aosp_15_r20/external/skia/modules/sksg/include/SkSGRenderEffect.h (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1*c8dee2aaSAndroid Build Coastguard Worker /*
2*c8dee2aaSAndroid Build Coastguard Worker  * Copyright 2019 Google Inc.
3*c8dee2aaSAndroid Build Coastguard Worker  *
4*c8dee2aaSAndroid Build Coastguard Worker  * Use of this source code is governed by a BSD-style license that can be
5*c8dee2aaSAndroid Build Coastguard Worker  * found in the LICENSE file.
6*c8dee2aaSAndroid Build Coastguard Worker  */
7*c8dee2aaSAndroid Build Coastguard Worker 
8*c8dee2aaSAndroid Build Coastguard Worker #ifndef SkSGRenderEffect_DEFINED
9*c8dee2aaSAndroid Build Coastguard Worker #define SkSGRenderEffect_DEFINED
10*c8dee2aaSAndroid Build Coastguard Worker 
11*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkBlendMode.h"
12*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkBlender.h"
13*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkColor.h"
14*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkImageFilter.h"
15*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkPoint.h"
16*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkRect.h"
17*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkRefCnt.h"
18*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkShader.h"
19*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkTileMode.h"
20*c8dee2aaSAndroid Build Coastguard Worker #include "include/effects/SkImageFilters.h"
21*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkAssert.h"
22*c8dee2aaSAndroid Build Coastguard Worker #include "modules/sksg/include/SkSGEffectNode.h"
23*c8dee2aaSAndroid Build Coastguard Worker #include "modules/sksg/include/SkSGNode.h"
24*c8dee2aaSAndroid Build Coastguard Worker 
25*c8dee2aaSAndroid Build Coastguard Worker #include <optional>
26*c8dee2aaSAndroid Build Coastguard Worker 
27*c8dee2aaSAndroid Build Coastguard Worker class SkCanvas;
28*c8dee2aaSAndroid Build Coastguard Worker class SkMatrix;
29*c8dee2aaSAndroid Build Coastguard Worker 
30*c8dee2aaSAndroid Build Coastguard Worker // TODO: merge EffectNode.h with this header
31*c8dee2aaSAndroid Build Coastguard Worker 
32*c8dee2aaSAndroid Build Coastguard Worker namespace sksg {
33*c8dee2aaSAndroid Build Coastguard Worker class InvalidationController;
34*c8dee2aaSAndroid Build Coastguard Worker class RenderNode;
35*c8dee2aaSAndroid Build Coastguard Worker 
36*c8dee2aaSAndroid Build Coastguard Worker /**
37*c8dee2aaSAndroid Build Coastguard Worker  * Shader base class.
38*c8dee2aaSAndroid Build Coastguard Worker  */
39*c8dee2aaSAndroid Build Coastguard Worker class Shader : public Node {
40*c8dee2aaSAndroid Build Coastguard Worker public:
41*c8dee2aaSAndroid Build Coastguard Worker     ~Shader() override;
42*c8dee2aaSAndroid Build Coastguard Worker 
getShader()43*c8dee2aaSAndroid Build Coastguard Worker     const sk_sp<SkShader>& getShader() const {
44*c8dee2aaSAndroid Build Coastguard Worker         SkASSERT(!this->hasInval());
45*c8dee2aaSAndroid Build Coastguard Worker         return fShader;
46*c8dee2aaSAndroid Build Coastguard Worker     }
47*c8dee2aaSAndroid Build Coastguard Worker 
48*c8dee2aaSAndroid Build Coastguard Worker protected:
49*c8dee2aaSAndroid Build Coastguard Worker     Shader();
50*c8dee2aaSAndroid Build Coastguard Worker 
51*c8dee2aaSAndroid Build Coastguard Worker     SkRect onRevalidate(InvalidationController*, const SkMatrix&) final;
52*c8dee2aaSAndroid Build Coastguard Worker 
53*c8dee2aaSAndroid Build Coastguard Worker     virtual sk_sp<SkShader> onRevalidateShader() = 0;
54*c8dee2aaSAndroid Build Coastguard Worker 
55*c8dee2aaSAndroid Build Coastguard Worker private:
56*c8dee2aaSAndroid Build Coastguard Worker     sk_sp<SkShader> fShader;
57*c8dee2aaSAndroid Build Coastguard Worker 
58*c8dee2aaSAndroid Build Coastguard Worker     using INHERITED = Node;
59*c8dee2aaSAndroid Build Coastguard Worker };
60*c8dee2aaSAndroid Build Coastguard Worker 
61*c8dee2aaSAndroid Build Coastguard Worker /**
62*c8dee2aaSAndroid Build Coastguard Worker  * Attaches a shader to the render DAG.
63*c8dee2aaSAndroid Build Coastguard Worker  */
64*c8dee2aaSAndroid Build Coastguard Worker class ShaderEffect final : public EffectNode {
65*c8dee2aaSAndroid Build Coastguard Worker public:
66*c8dee2aaSAndroid Build Coastguard Worker     ~ShaderEffect() override;
67*c8dee2aaSAndroid Build Coastguard Worker 
68*c8dee2aaSAndroid Build Coastguard Worker     static sk_sp<ShaderEffect> Make(sk_sp<RenderNode> child, sk_sp<Shader> shader = nullptr);
69*c8dee2aaSAndroid Build Coastguard Worker 
70*c8dee2aaSAndroid Build Coastguard Worker     void setShader(sk_sp<Shader>);
71*c8dee2aaSAndroid Build Coastguard Worker 
72*c8dee2aaSAndroid Build Coastguard Worker protected:
73*c8dee2aaSAndroid Build Coastguard Worker     void onRender(SkCanvas*, const RenderContext*) const override;
74*c8dee2aaSAndroid Build Coastguard Worker 
75*c8dee2aaSAndroid Build Coastguard Worker     SkRect onRevalidate(InvalidationController*, const SkMatrix&) override;
76*c8dee2aaSAndroid Build Coastguard Worker 
77*c8dee2aaSAndroid Build Coastguard Worker private:
78*c8dee2aaSAndroid Build Coastguard Worker     ShaderEffect(sk_sp<RenderNode> child, sk_sp<Shader> shader);
79*c8dee2aaSAndroid Build Coastguard Worker 
80*c8dee2aaSAndroid Build Coastguard Worker     sk_sp<Shader> fShader;
81*c8dee2aaSAndroid Build Coastguard Worker 
82*c8dee2aaSAndroid Build Coastguard Worker     using INHERITED = EffectNode;
83*c8dee2aaSAndroid Build Coastguard Worker };
84*c8dee2aaSAndroid Build Coastguard Worker 
85*c8dee2aaSAndroid Build Coastguard Worker /**
86*c8dee2aaSAndroid Build Coastguard Worker  * Attaches a mask shader to the render DAG.
87*c8dee2aaSAndroid Build Coastguard Worker  */
88*c8dee2aaSAndroid Build Coastguard Worker class MaskShaderEffect final : public EffectNode {
89*c8dee2aaSAndroid Build Coastguard Worker public:
90*c8dee2aaSAndroid Build Coastguard Worker     static sk_sp<MaskShaderEffect> Make(sk_sp<RenderNode>, sk_sp<SkShader> = nullptr);
91*c8dee2aaSAndroid Build Coastguard Worker 
92*c8dee2aaSAndroid Build Coastguard Worker     SG_ATTRIBUTE(Shader, sk_sp<SkShader>, fShader)
93*c8dee2aaSAndroid Build Coastguard Worker 
94*c8dee2aaSAndroid Build Coastguard Worker protected:
95*c8dee2aaSAndroid Build Coastguard Worker     void onRender(SkCanvas*, const RenderContext*) const override;
96*c8dee2aaSAndroid Build Coastguard Worker 
97*c8dee2aaSAndroid Build Coastguard Worker private:
98*c8dee2aaSAndroid Build Coastguard Worker     MaskShaderEffect(sk_sp<RenderNode>, sk_sp<SkShader>);
99*c8dee2aaSAndroid Build Coastguard Worker 
100*c8dee2aaSAndroid Build Coastguard Worker     sk_sp<SkShader> fShader;
101*c8dee2aaSAndroid Build Coastguard Worker 
102*c8dee2aaSAndroid Build Coastguard Worker     using INHERITED = EffectNode;
103*c8dee2aaSAndroid Build Coastguard Worker };
104*c8dee2aaSAndroid Build Coastguard Worker 
105*c8dee2aaSAndroid Build Coastguard Worker /**
106*c8dee2aaSAndroid Build Coastguard Worker  * ImageFilter base class.
107*c8dee2aaSAndroid Build Coastguard Worker  */
108*c8dee2aaSAndroid Build Coastguard Worker class ImageFilter : public Node {
109*c8dee2aaSAndroid Build Coastguard Worker public:
110*c8dee2aaSAndroid Build Coastguard Worker     ~ImageFilter() override;
111*c8dee2aaSAndroid Build Coastguard Worker 
getFilter()112*c8dee2aaSAndroid Build Coastguard Worker     const sk_sp<SkImageFilter>& getFilter() const {
113*c8dee2aaSAndroid Build Coastguard Worker         SkASSERT(!this->hasInval());
114*c8dee2aaSAndroid Build Coastguard Worker         return fFilter;
115*c8dee2aaSAndroid Build Coastguard Worker     }
116*c8dee2aaSAndroid Build Coastguard Worker 
117*c8dee2aaSAndroid Build Coastguard Worker     SG_ATTRIBUTE(CropRect, SkImageFilters::CropRect, fCropRect)
118*c8dee2aaSAndroid Build Coastguard Worker 
119*c8dee2aaSAndroid Build Coastguard Worker protected:
120*c8dee2aaSAndroid Build Coastguard Worker     ImageFilter();
121*c8dee2aaSAndroid Build Coastguard Worker 
122*c8dee2aaSAndroid Build Coastguard Worker     SkRect onRevalidate(InvalidationController*, const SkMatrix&) final;
123*c8dee2aaSAndroid Build Coastguard Worker 
124*c8dee2aaSAndroid Build Coastguard Worker     virtual sk_sp<SkImageFilter> onRevalidateFilter() = 0;
125*c8dee2aaSAndroid Build Coastguard Worker 
126*c8dee2aaSAndroid Build Coastguard Worker private:
127*c8dee2aaSAndroid Build Coastguard Worker     sk_sp<SkImageFilter>     fFilter;
128*c8dee2aaSAndroid Build Coastguard Worker     SkImageFilters::CropRect fCropRect = std::nullopt;
129*c8dee2aaSAndroid Build Coastguard Worker 
130*c8dee2aaSAndroid Build Coastguard Worker     using INHERITED = Node;
131*c8dee2aaSAndroid Build Coastguard Worker };
132*c8dee2aaSAndroid Build Coastguard Worker 
133*c8dee2aaSAndroid Build Coastguard Worker /**
134*c8dee2aaSAndroid Build Coastguard Worker  * Attaches an ImageFilter (chain) to the render DAG.
135*c8dee2aaSAndroid Build Coastguard Worker  */
136*c8dee2aaSAndroid Build Coastguard Worker class ImageFilterEffect final : public EffectNode {
137*c8dee2aaSAndroid Build Coastguard Worker public:
138*c8dee2aaSAndroid Build Coastguard Worker     ~ImageFilterEffect() override;
139*c8dee2aaSAndroid Build Coastguard Worker 
140*c8dee2aaSAndroid Build Coastguard Worker     static sk_sp<RenderNode> Make(sk_sp<RenderNode> child, sk_sp<ImageFilter> filter);
141*c8dee2aaSAndroid Build Coastguard Worker 
142*c8dee2aaSAndroid Build Coastguard Worker     enum class Cropping {
143*c8dee2aaSAndroid Build Coastguard Worker         kNone,    // Doesn't use a crop rect.
144*c8dee2aaSAndroid Build Coastguard Worker         kContent, // Uses the content bounding box as a crop rect.
145*c8dee2aaSAndroid Build Coastguard Worker     };
146*c8dee2aaSAndroid Build Coastguard Worker 
147*c8dee2aaSAndroid Build Coastguard Worker     SG_ATTRIBUTE(Cropping, Cropping, fCropping)
148*c8dee2aaSAndroid Build Coastguard Worker 
149*c8dee2aaSAndroid Build Coastguard Worker protected:
150*c8dee2aaSAndroid Build Coastguard Worker     void onRender(SkCanvas*, const RenderContext*) const override;
151*c8dee2aaSAndroid Build Coastguard Worker     const RenderNode* onNodeAt(const SkPoint&)     const override;
152*c8dee2aaSAndroid Build Coastguard Worker 
153*c8dee2aaSAndroid Build Coastguard Worker     SkRect onRevalidate(InvalidationController*, const SkMatrix&) override;
154*c8dee2aaSAndroid Build Coastguard Worker 
155*c8dee2aaSAndroid Build Coastguard Worker private:
156*c8dee2aaSAndroid Build Coastguard Worker     ImageFilterEffect(sk_sp<RenderNode> child, sk_sp<ImageFilter> filter);
157*c8dee2aaSAndroid Build Coastguard Worker 
158*c8dee2aaSAndroid Build Coastguard Worker     sk_sp<ImageFilter> fImageFilter;
159*c8dee2aaSAndroid Build Coastguard Worker     Cropping           fCropping = Cropping::kNone;
160*c8dee2aaSAndroid Build Coastguard Worker 
161*c8dee2aaSAndroid Build Coastguard Worker     using INHERITED = EffectNode;
162*c8dee2aaSAndroid Build Coastguard Worker };
163*c8dee2aaSAndroid Build Coastguard Worker 
164*c8dee2aaSAndroid Build Coastguard Worker /**
165*c8dee2aaSAndroid Build Coastguard Worker  * Wrapper for externally-managed SkImageFilters.
166*c8dee2aaSAndroid Build Coastguard Worker  */
167*c8dee2aaSAndroid Build Coastguard Worker class ExternalImageFilter final : public ImageFilter {
168*c8dee2aaSAndroid Build Coastguard Worker public:
169*c8dee2aaSAndroid Build Coastguard Worker     ~ExternalImageFilter() override;
170*c8dee2aaSAndroid Build Coastguard Worker 
Make()171*c8dee2aaSAndroid Build Coastguard Worker     static sk_sp<ExternalImageFilter> Make() {
172*c8dee2aaSAndroid Build Coastguard Worker         return sk_sp<ExternalImageFilter>(new ExternalImageFilter());
173*c8dee2aaSAndroid Build Coastguard Worker     }
174*c8dee2aaSAndroid Build Coastguard Worker 
175*c8dee2aaSAndroid Build Coastguard Worker     SG_ATTRIBUTE(ImageFilter, sk_sp<SkImageFilter>, fImageFilter)
176*c8dee2aaSAndroid Build Coastguard Worker 
177*c8dee2aaSAndroid Build Coastguard Worker private:
178*c8dee2aaSAndroid Build Coastguard Worker     ExternalImageFilter();
179*c8dee2aaSAndroid Build Coastguard Worker 
onRevalidateFilter()180*c8dee2aaSAndroid Build Coastguard Worker     sk_sp<SkImageFilter> onRevalidateFilter() override { return fImageFilter; }
181*c8dee2aaSAndroid Build Coastguard Worker 
182*c8dee2aaSAndroid Build Coastguard Worker     sk_sp<SkImageFilter> fImageFilter;
183*c8dee2aaSAndroid Build Coastguard Worker };
184*c8dee2aaSAndroid Build Coastguard Worker 
185*c8dee2aaSAndroid Build Coastguard Worker /**
186*c8dee2aaSAndroid Build Coastguard Worker  * SkDropShadowImageFilter node.
187*c8dee2aaSAndroid Build Coastguard Worker  */
188*c8dee2aaSAndroid Build Coastguard Worker class DropShadowImageFilter final : public ImageFilter {
189*c8dee2aaSAndroid Build Coastguard Worker public:
190*c8dee2aaSAndroid Build Coastguard Worker     ~DropShadowImageFilter() override;
191*c8dee2aaSAndroid Build Coastguard Worker 
192*c8dee2aaSAndroid Build Coastguard Worker     static sk_sp<DropShadowImageFilter> Make();
193*c8dee2aaSAndroid Build Coastguard Worker 
194*c8dee2aaSAndroid Build Coastguard Worker     enum class Mode { kShadowAndForeground, kShadowOnly };
195*c8dee2aaSAndroid Build Coastguard Worker 
196*c8dee2aaSAndroid Build Coastguard Worker     SG_ATTRIBUTE(Offset, SkVector, fOffset)
197*c8dee2aaSAndroid Build Coastguard Worker     SG_ATTRIBUTE(Sigma , SkVector, fSigma )
198*c8dee2aaSAndroid Build Coastguard Worker     SG_ATTRIBUTE(Color , SkColor , fColor )
199*c8dee2aaSAndroid Build Coastguard Worker     SG_ATTRIBUTE(Mode  , Mode    , fMode  )
200*c8dee2aaSAndroid Build Coastguard Worker 
201*c8dee2aaSAndroid Build Coastguard Worker protected:
202*c8dee2aaSAndroid Build Coastguard Worker     sk_sp<SkImageFilter> onRevalidateFilter() override;
203*c8dee2aaSAndroid Build Coastguard Worker 
204*c8dee2aaSAndroid Build Coastguard Worker private:
205*c8dee2aaSAndroid Build Coastguard Worker     explicit DropShadowImageFilter();
206*c8dee2aaSAndroid Build Coastguard Worker 
207*c8dee2aaSAndroid Build Coastguard Worker     SkVector             fOffset = { 0, 0 },
208*c8dee2aaSAndroid Build Coastguard Worker                          fSigma  = { 0, 0 };
209*c8dee2aaSAndroid Build Coastguard Worker     SkColor              fColor  = SK_ColorBLACK;
210*c8dee2aaSAndroid Build Coastguard Worker     Mode                 fMode   = Mode::kShadowAndForeground;
211*c8dee2aaSAndroid Build Coastguard Worker 
212*c8dee2aaSAndroid Build Coastguard Worker     using INHERITED = ImageFilter;
213*c8dee2aaSAndroid Build Coastguard Worker };
214*c8dee2aaSAndroid Build Coastguard Worker 
215*c8dee2aaSAndroid Build Coastguard Worker /**
216*c8dee2aaSAndroid Build Coastguard Worker  * SkBlurImageFilter node.
217*c8dee2aaSAndroid Build Coastguard Worker  */
218*c8dee2aaSAndroid Build Coastguard Worker class BlurImageFilter final : public ImageFilter {
219*c8dee2aaSAndroid Build Coastguard Worker public:
220*c8dee2aaSAndroid Build Coastguard Worker     ~BlurImageFilter() override;
221*c8dee2aaSAndroid Build Coastguard Worker 
222*c8dee2aaSAndroid Build Coastguard Worker     static sk_sp<BlurImageFilter> Make();
223*c8dee2aaSAndroid Build Coastguard Worker 
224*c8dee2aaSAndroid Build Coastguard Worker     SG_ATTRIBUTE(Sigma   , SkVector  , fSigma   )
225*c8dee2aaSAndroid Build Coastguard Worker     SG_ATTRIBUTE(TileMode, SkTileMode, fTileMode)
226*c8dee2aaSAndroid Build Coastguard Worker 
227*c8dee2aaSAndroid Build Coastguard Worker protected:
228*c8dee2aaSAndroid Build Coastguard Worker     sk_sp<SkImageFilter> onRevalidateFilter() override;
229*c8dee2aaSAndroid Build Coastguard Worker 
230*c8dee2aaSAndroid Build Coastguard Worker private:
231*c8dee2aaSAndroid Build Coastguard Worker     explicit BlurImageFilter();
232*c8dee2aaSAndroid Build Coastguard Worker 
233*c8dee2aaSAndroid Build Coastguard Worker     SkVector   fSigma    = { 0, 0 };
234*c8dee2aaSAndroid Build Coastguard Worker     SkTileMode fTileMode = SkTileMode::kDecal;
235*c8dee2aaSAndroid Build Coastguard Worker 
236*c8dee2aaSAndroid Build Coastguard Worker     using INHERITED = ImageFilter;
237*c8dee2aaSAndroid Build Coastguard Worker };
238*c8dee2aaSAndroid Build Coastguard Worker 
239*c8dee2aaSAndroid Build Coastguard Worker /**
240*c8dee2aaSAndroid Build Coastguard Worker  * Applies an SkBlender to descendant render nodes.
241*c8dee2aaSAndroid Build Coastguard Worker  */
242*c8dee2aaSAndroid Build Coastguard Worker class BlenderEffect final : public EffectNode {
243*c8dee2aaSAndroid Build Coastguard Worker public:
244*c8dee2aaSAndroid Build Coastguard Worker     ~BlenderEffect() override;
245*c8dee2aaSAndroid Build Coastguard Worker 
246*c8dee2aaSAndroid Build Coastguard Worker     static sk_sp<BlenderEffect> Make(sk_sp<RenderNode> child, sk_sp<SkBlender> = nullptr);
247*c8dee2aaSAndroid Build Coastguard Worker 
248*c8dee2aaSAndroid Build Coastguard Worker     SG_ATTRIBUTE(Blender, sk_sp<SkBlender>, fBlender)
249*c8dee2aaSAndroid Build Coastguard Worker 
250*c8dee2aaSAndroid Build Coastguard Worker protected:
251*c8dee2aaSAndroid Build Coastguard Worker     void onRender(SkCanvas*, const RenderContext*) const override;
252*c8dee2aaSAndroid Build Coastguard Worker     const RenderNode* onNodeAt(const SkPoint&)     const override;
253*c8dee2aaSAndroid Build Coastguard Worker 
254*c8dee2aaSAndroid Build Coastguard Worker private:
255*c8dee2aaSAndroid Build Coastguard Worker     BlenderEffect(sk_sp<RenderNode>, sk_sp<SkBlender>);
256*c8dee2aaSAndroid Build Coastguard Worker 
257*c8dee2aaSAndroid Build Coastguard Worker     sk_sp<SkBlender> fBlender;
258*c8dee2aaSAndroid Build Coastguard Worker 
259*c8dee2aaSAndroid Build Coastguard Worker     using INHERITED = EffectNode;
260*c8dee2aaSAndroid Build Coastguard Worker };
261*c8dee2aaSAndroid Build Coastguard Worker 
262*c8dee2aaSAndroid Build Coastguard Worker class LayerEffect final : public EffectNode {
263*c8dee2aaSAndroid Build Coastguard Worker public:
264*c8dee2aaSAndroid Build Coastguard Worker     ~LayerEffect() override;
265*c8dee2aaSAndroid Build Coastguard Worker 
266*c8dee2aaSAndroid Build Coastguard Worker     static sk_sp<LayerEffect> Make(sk_sp<RenderNode> child,
267*c8dee2aaSAndroid Build Coastguard Worker                                    SkBlendMode mode = SkBlendMode::kSrcOver);
268*c8dee2aaSAndroid Build Coastguard Worker 
269*c8dee2aaSAndroid Build Coastguard Worker     SG_ATTRIBUTE(Mode, SkBlendMode, fMode)
270*c8dee2aaSAndroid Build Coastguard Worker 
271*c8dee2aaSAndroid Build Coastguard Worker private:
272*c8dee2aaSAndroid Build Coastguard Worker     LayerEffect(sk_sp<RenderNode> child, SkBlendMode mode);
273*c8dee2aaSAndroid Build Coastguard Worker 
274*c8dee2aaSAndroid Build Coastguard Worker     void onRender(SkCanvas*, const RenderContext*) const override;
275*c8dee2aaSAndroid Build Coastguard Worker 
276*c8dee2aaSAndroid Build Coastguard Worker     SkBlendMode fMode;
277*c8dee2aaSAndroid Build Coastguard Worker 
278*c8dee2aaSAndroid Build Coastguard Worker     using INHERITED = EffectNode;
279*c8dee2aaSAndroid Build Coastguard Worker };
280*c8dee2aaSAndroid Build Coastguard Worker 
281*c8dee2aaSAndroid Build Coastguard Worker } // namespace sksg
282*c8dee2aaSAndroid Build Coastguard Worker 
283*c8dee2aaSAndroid Build Coastguard Worker #endif // SkSGRenderEffect_DEFINED
284