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