• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2024 Google LLC
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7 
8 #ifndef skgpu_graphite_precompile_PrecompileShader_DEFINED
9 #define skgpu_graphite_precompile_PrecompileShader_DEFINED
10 
11 #include "include/gpu/graphite/precompile/PrecompileBase.h"
12 
13 #include "include/core/SkBlendMode.h"
14 #include "include/core/SkImageInfo.h"
15 #include "include/effects/SkGradientShader.h"
16 
17 class SkColorSpace;
18 
19 namespace skgpu::graphite {
20 
21 class PrecompileBlender;
22 class PrecompileColorFilter;
23 class PrecompileShaderPriv;
24 
25 /** \class PrecompileShader
26     This class corresponds to the SkShader class in the main API.
27 */
28 class SK_API PrecompileShader : public PrecompileBase {
29 public:
30     /**
31      *  This is the Precompile correlate to SkShader::makeWithLocalMatrix. The actual matrix
32      *  involved is abstracted away, except for whether or the not the matrix involves perspective
33      *  so the correct generated shader variation is chosen.
34      *  The PrecompileShaders::LocalMatrix factory can be used to generate a set of shaders
35      *  that would've been generated via multiple makeWithLocalMatrix calls. That is, rather than
36      *  performing:
37      *     sk_sp<PrecompileShader> option1 = source1->makeWithLocalMatrix(false);
38      *     sk_sp<PrecompileShader> option2 = source2->makeWithLocalMatrix(false);
39      *  one could call:
40      *     sk_sp<PrecompileShader> combinedOptions = LocalMatrix({ source1, source2 }, false);
41      */
42     sk_sp<PrecompileShader> makeWithLocalMatrix(bool isPerspective) const;
43 
44     /**
45      *  This is the Precompile correlate to SkShader::makeWithColorFilter.
46      *  The PrecompileShaders::ColorFilter factory can be used to generate a set of shaders that
47      *  would've been generated via multiple makeWithColorFilter calls. That is, rather than
48      *  performing:
49      *     sk_sp<PrecompileShader> option1 = source->makeWithColorFilter(colorFilter1);
50      *     sk_sp<PrecompileShader> option2 = source->makeWithColorFilter(colorFilter2);
51      *  one could call:
52      *     sk_sp<PrecompileShader> combinedOptions = ColorFilter({ source },
53      *                                                           { colorFilter1, colorFilter2 });
54      *  With an alternative use case one could also use the ColorFilter factory thusly:
55      *     sk_sp<PrecompileShader> combinedOptions = ColorFilter({ source1, source2 },
56      *                                                           { colorFilter });
57      */
58     sk_sp<PrecompileShader> makeWithColorFilter(sk_sp<PrecompileColorFilter>) const;
59 
60     /**
61      *  This is the Precompile correlate to SkShader::makeWithWorkingColorSpace.
62      *  The PrecompileShaders::WorkingColorSpace factory can be used to generate a set of shaders
63      *  that would've been generated via multiple makeWithWorkingColorSpace calls. That is, rather
64      *  than performing:
65      *     sk_sp<PrecompileShader> option1 = source->makeWithWorkingColorSpace(colorSpace1);
66      *     sk_sp<PrecompileShader> option2 = source->makeWithWorkingColorSpace(colorSpace2);
67      *  one could call:
68      *     sk_sp<PrecompileShader> combinedOptions = WorkingColorSpace({ source },
69      *                                                                 { colorSpace1,
70      *                                                                   colorSpace2 });
71      *  With an alternative use case one could also use the WorkingColorSpace factory thusly:
72      *     sk_sp<PrecompileShader> combinedOptions = WorkingColorSpace({ source1, source2 },
73      *                                                                 { colorSpace });
74      */
75     sk_sp<PrecompileShader> makeWithWorkingColorSpace(sk_sp<SkColorSpace>) const;
76 
77     // Provides access to functions that aren't part of the public API.
78     PrecompileShaderPriv priv();
79     const PrecompileShaderPriv priv() const;  // NOLINT(readability-const-return-type)
80 
81 protected:
82     friend class PrecompileShaderPriv;
83 
PrecompileShader()84     PrecompileShader() : PrecompileBase(Type::kShader) {}
85     ~PrecompileShader() override;
86 
isConstant(int)87     virtual bool isConstant(int /* desiredCombination */) const { return false; }
88 
isALocalMatrixShader()89     virtual bool isALocalMatrixShader() const { return false; }
90 };
91 
92 //--------------------------------------------------------------------------------------------------
93 // This is the Precompile correlate to the SkShaders namespace in the main API
94 namespace PrecompileShaders {
95     // --- This block of eight matches the SkShaders factories in SkShader.h
96     // Note that some of the details of the main API have been elided since they don't impact
97     // the generated shader (e.g., the color parameter to the Color() factories).
98     SK_API sk_sp<PrecompileShader> Empty();
99     SK_API sk_sp<PrecompileShader> Color();
100     SK_API sk_sp<PrecompileShader> Color(sk_sp<SkColorSpace>);
101     SK_API sk_sp<PrecompileShader> Blend(SkSpan<const SkBlendMode> blendModes,
102                                          SkSpan<const sk_sp<PrecompileShader>> dsts,
103                                          SkSpan<const sk_sp<PrecompileShader>> srcs);
104     SK_API sk_sp<PrecompileShader> Blend(SkSpan<const sk_sp<PrecompileBlender>> blenders,
105                                          SkSpan<const sk_sp<PrecompileShader>> dsts,
106                                          SkSpan<const sk_sp<PrecompileShader>> srcs);
107     SK_API sk_sp<PrecompileShader> CoordClamp(SkSpan<const sk_sp<PrecompileShader>>);
108 
109     // In the main Skia API ImageShaders are usually created via a SkImage::makeShader call.
110     // Since the SkImage used to create the ImageShader is unlikely to be present at precompilation
111     // time this entry point allows the equivalent precompilation program structure to be created.
112     // Note that this factory is for non-YUV SkImages, the YUVImage factory (below) should be used
113     // to represent the shading and sampling required for YUV images.
114     SK_API sk_sp<PrecompileShader> Image(SkSpan<const SkColorInfo> = {},
115                                          SkSpan<const SkTileMode> = {});
116     // As with the above Image call, raw ImageShaders are usually created via an
117     // SkImage::makeRawShader call. The RawImage call allows the equivalent precompilation
118     // program structure to be created without needing the SkImage.
119     SK_API sk_sp<PrecompileShader> RawImage(SkSpan<const SkColorInfo> = {},
120                                             SkSpan<const SkTileMode> = {});
121 
122     // In the main Skia API, the specifics of the SkImage used for the SkImage::makeShader call
123     // can determine whether normal or YUV sampling is required. This entry point allows clients
124     // to specify that the future image will be a YUV image.
125     SK_API sk_sp<PrecompileShader> YUVImage();
126 
127     // --- This block of two matches the SkShaders factories in SkPerlinNoiseShader.h
128     // Again, most of the details have been elided.
129     SK_API sk_sp<PrecompileShader> MakeFractalNoise();
130     SK_API sk_sp<PrecompileShader> MakeTurbulence();
131 
132     // --- This block of four matches all the factories in SkGradientShader (SkGradientShader.h)
133     SK_API sk_sp<PrecompileShader> LinearGradient(
134             SkGradientShader::Interpolation = SkGradientShader::Interpolation());
135     SK_API sk_sp<PrecompileShader> RadialGradient(
136             SkGradientShader::Interpolation = SkGradientShader::Interpolation());
137     SK_API sk_sp<PrecompileShader> TwoPointConicalGradient(
138             SkGradientShader::Interpolation = SkGradientShader::Interpolation());
139     SK_API sk_sp<PrecompileShader> SweepGradient(
140             SkGradientShader::Interpolation = SkGradientShader::Interpolation());
141 
142     // Normally, SkPicture shaders are only created via SkPicture::makeShader. Since the
143     // SkPicture to be drawn, most likely, won't be available at precompilation time, this
144     // entry point can be used to create a precompilation equivalent.
145     // Note: this will precompile the program that draws the SkPicture. It, obviously, won't
146     // precompile any SkPaints within the SkPicture.
147     SK_API sk_sp<PrecompileShader> Picture();
148 
149     // Normally, LocalMatrixShaders are only created via SkShader::makeWithLocalMatrix.
150     // However, in the combination API, clients may want to create a set of precompile
151     // LocalMatrixShaders (i.e., pass an SkSpan to the factory function vs just creating a
152     // single option). This entry point allows that use case.
153     // Note: PrecompileShader::makeWithLocalMatrix() can still be used and works as expected.
154     SK_API sk_sp<PrecompileShader> LocalMatrix(SkSpan<const sk_sp<PrecompileShader>> wrapped,
155                                                bool isPerspective = false);
156 
157     // Normally, ColorFilterShaders are only created via SkShader::makeWithColorFilter.
158     // However, in the combination API, clients may want to create a set of precompile
159     // ColorFilterShaders (i.e., pass SkSpans to the factory function vs just creating a
160     // single option). This entry point allows that use case.
161     // Note: PrecompileShader::makeWithColorFilter can still be used and works as expected.
162     SK_API sk_sp<PrecompileShader> ColorFilter(
163             SkSpan<const sk_sp<PrecompileShader>> shaders,
164             SkSpan<const sk_sp<PrecompileColorFilter>> colorFilters);
165 
166     // Normally, WorkingColorSpaceShaders are only created via SkShader::makeWithWorkingColorSpace.
167     // However, in the combination API, clients may want to create a set of precompile
168     // WorkingColorSpaceShaders (i.e., pass SkSpans to the factory function vs just creating a
169     // single option). This entry point allows that use case.
170     // Note: PrecompileShader::makeWithWorkingColorSpace can still be used and works as expected.
171     SK_API sk_sp<PrecompileShader> WorkingColorSpace(SkSpan<const sk_sp<PrecompileShader>> shaders,
172                                                      SkSpan<const sk_sp<SkColorSpace>> colorSpaces);
173 
174 } // namespace PrecompileShaders
175 
176 } // namespace skgpu::graphite
177 
178 #endif // skgpu_graphite_precompile_PrecompileShader_DEFINED
179