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