1 /* 2 * Copyright 2022 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_KeyHelpers_DEFINED 9 #define skgpu_graphite_KeyHelpers_DEFINED 10 11 #include "include/core/SkBlendMode.h" 12 #include "include/core/SkM44.h" 13 #include "include/core/SkSamplingOptions.h" 14 #include "include/core/SkShader.h" 15 #include "include/core/SkSpan.h" 16 #include "include/core/SkTileMode.h" 17 #include "include/effects/SkGradientShader.h" 18 #include "include/gpu/graphite/Context.h" 19 #include "include/private/SkColorData.h" 20 #include "src/core/SkColorSpaceXformSteps.h" 21 #include "src/gpu/graphite/TextureProxy.h" 22 #include "src/shaders/SkShaderBase.h" 23 24 class SkData; 25 class SkRuntimeEffect; 26 27 namespace skgpu::graphite { 28 29 class KeyContext; 30 class PaintParamsKeyBuilder; 31 class PipelineDataGatherer; 32 class UniquePaintParamsID; 33 enum class ReadSwizzle; 34 35 /** 36 * The KeyHelpers can be used to manually construct an SkPaintParamsKey. 37 * 38 * TODO: If we restructure how the keys are made, we can utilize a single block type for the 39 * different blend blocks outlined below. The different Src/Dst pairings could instead be encoded 40 * as parent-child relationships. 41 */ 42 43 struct PassthroughShaderBlock { 44 45 static void BeginBlock(const KeyContext&, 46 PaintParamsKeyBuilder*, 47 PipelineDataGatherer*); 48 49 }; 50 51 struct PassthroughBlenderBlock { 52 53 static void BeginBlock(const KeyContext&, 54 PaintParamsKeyBuilder*, 55 PipelineDataGatherer*); 56 57 }; 58 59 struct SolidColorShaderBlock { 60 61 static void BeginBlock(const KeyContext&, 62 PaintParamsKeyBuilder*, 63 PipelineDataGatherer*, 64 const SkPMColor4f&); 65 66 }; 67 68 struct GradientShaderBlocks { 69 70 struct GradientData { 71 // TODO: For the sprint we only support 8 stops in the gradients 72 static constexpr int kMaxStops = 8; 73 74 // This ctor is used during pre-compilation when we don't have enough information to 75 // extract uniform data. However, we must be able to provide enough data to make all the 76 // relevant decisions about which code snippets to use. 77 GradientData(SkShaderBase::GradientType, int numStops); 78 79 // This ctor is used when extracting information from PaintParams. It must provide 80 // enough data to generate the uniform data the selected code snippet will require. 81 GradientData(SkShaderBase::GradientType, 82 SkPoint point0, SkPoint point1, 83 float radius0, float radius1, 84 float bias, float scale, 85 SkTileMode, 86 int numStops, 87 const SkPMColor4f* colors, 88 float* offsets, 89 const SkGradientShader::Interpolation&); 90 91 bool operator==(const GradientData& rhs) const { 92 return fType == rhs.fType && 93 fPoints[0] == rhs.fPoints[0] && 94 fPoints[1] == rhs.fPoints[1] && 95 fRadii[0] == rhs.fRadii[0] && 96 fRadii[1] == rhs.fRadii[1] && 97 fBias == rhs.fBias && 98 fScale == rhs.fScale && 99 fTM == rhs.fTM && 100 fNumStops == rhs.fNumStops && 101 !memcmp(fColors, rhs.fColors, sizeof(fColors)) && 102 !memcmp(fOffsets, rhs.fOffsets, sizeof(fOffsets)); 103 } 104 bool operator!=(const GradientData& rhs) const { return !(*this == rhs); } 105 106 // Layout options. 107 SkShaderBase::GradientType fType; 108 SkPoint fPoints[2]; 109 float fRadii[2]; 110 111 // Layout options for sweep gradient. 112 float fBias; 113 float fScale; 114 115 SkTileMode fTM; 116 int fNumStops; 117 SkPMColor4f fColors[kMaxStops]; 118 float fOffsets[kMaxStops]; 119 120 SkGradientShader::Interpolation fInterpolation; 121 }; 122 123 static void BeginBlock(const KeyContext&, 124 PaintParamsKeyBuilder*, 125 PipelineDataGatherer*, 126 const GradientData&); 127 128 }; 129 130 struct LocalMatrixShaderBlock { 131 132 struct LMShaderData { LMShaderDataLocalMatrixShaderBlock::LMShaderData133 LMShaderData(const SkMatrix& localMatrix) 134 : fLocalMatrix(localMatrix) { 135 } 136 137 const SkM44 fLocalMatrix; 138 }; 139 140 static void BeginBlock(const KeyContext&, 141 PaintParamsKeyBuilder*, 142 PipelineDataGatherer*, 143 const LMShaderData*); 144 145 }; 146 147 struct ImageShaderBlock { 148 149 struct ImageData { 150 ImageData(const SkSamplingOptions& sampling, 151 SkTileMode tileModeX, 152 SkTileMode tileModeY, 153 SkRect subset, 154 ReadSwizzle readSwizzle); 155 156 SkSamplingOptions fSampling; 157 SkTileMode fTileModes[2]; 158 SkRect fSubset; 159 ReadSwizzle fReadSwizzle; 160 161 SkColorSpaceXformSteps fSteps; 162 163 // TODO: Currently this is only filled in when we're generating the key from an actual 164 // SkImageShader. In the pre-compile case we will need to create a Graphite promise 165 // image which holds the appropriate data. 166 sk_sp<TextureProxy> fTextureProxy; 167 }; 168 169 // The gatherer and imageData should be null or non-null together 170 static void BeginBlock(const KeyContext&, 171 PaintParamsKeyBuilder*, 172 PipelineDataGatherer*, 173 const ImageData*); 174 175 }; 176 177 struct PorterDuffBlendShaderBlock { 178 struct PorterDuffBlendShaderData { 179 SkSpan<const float> fPorterDuffConstants; 180 }; 181 182 static void BeginBlock(const KeyContext&, 183 PaintParamsKeyBuilder*, 184 PipelineDataGatherer*, 185 const PorterDuffBlendShaderData&); 186 }; 187 188 struct BlendShaderBlock { 189 /** 190 * Blend shader blocks are used to blend the output of two shaders. 191 */ 192 struct BlendShaderData { 193 SkBlendMode fBM; 194 }; 195 196 static void BeginBlock(const KeyContext&, 197 PaintParamsKeyBuilder*, 198 PipelineDataGatherer*, 199 const BlendShaderData&); 200 }; 201 202 struct ColorFilterShaderBlock { 203 static void BeginBlock(const KeyContext&, 204 PaintParamsKeyBuilder*, 205 PipelineDataGatherer*); 206 }; 207 208 struct MatrixColorFilterBlock { 209 struct MatrixColorFilterData { MatrixColorFilterDataMatrixColorFilterBlock::MatrixColorFilterData210 MatrixColorFilterData(const float matrix[20], 211 bool inHSLA) 212 : fMatrix(matrix[ 0], matrix[ 1], matrix[ 2], matrix[ 3], 213 matrix[ 5], matrix[ 6], matrix[ 7], matrix[ 8], 214 matrix[10], matrix[11], matrix[12], matrix[13], 215 matrix[15], matrix[16], matrix[17], matrix[18]) 216 , fTranslate{matrix[4], matrix[9], matrix[14], matrix[19]} 217 , fInHSLA(inHSLA) { 218 } 219 220 SkM44 fMatrix; 221 SkV4 fTranslate; 222 bool fInHSLA; 223 }; 224 225 // The gatherer and matrixCFData should be null or non-null together 226 static void BeginBlock(const KeyContext&, 227 PaintParamsKeyBuilder*, 228 PipelineDataGatherer*, 229 const MatrixColorFilterData*); 230 }; 231 232 struct BlendColorFilterBlock { 233 /** 234 * Blend color filter blocks are used to blend the output of a shader with a color uniform. 235 */ 236 struct BlendColorFilterData { BlendColorFilterDataBlendColorFilterBlock::BlendColorFilterData237 BlendColorFilterData(SkBlendMode blendMode, const SkPMColor4f& srcColor) 238 : fBlendMode(blendMode) 239 , fSrcColor(srcColor) { 240 } 241 242 SkBlendMode fBlendMode; 243 SkPMColor4f fSrcColor; 244 }; 245 246 static void BeginBlock(const KeyContext&, 247 PaintParamsKeyBuilder*, 248 PipelineDataGatherer*, 249 const BlendColorFilterData*); 250 }; 251 252 struct ComposeColorFilterBlock { 253 static void BeginBlock(const KeyContext&, 254 PaintParamsKeyBuilder*, 255 PipelineDataGatherer*); 256 }; 257 258 struct TableColorFilterBlock { 259 struct TableColorFilterData { 260 TableColorFilterData(); 261 262 sk_sp<TextureProxy> fTextureProxy; 263 }; 264 265 static void BeginBlock(const KeyContext&, 266 PaintParamsKeyBuilder*, 267 PipelineDataGatherer*, 268 const TableColorFilterData&); 269 }; 270 271 struct GaussianColorFilterBlock { 272 static void BeginBlock(const KeyContext&, 273 PaintParamsKeyBuilder*, 274 PipelineDataGatherer*); 275 }; 276 277 struct ColorSpaceTransformBlock { 278 struct ColorSpaceTransformData { 279 ColorSpaceTransformData(const SkColorSpace* src, 280 SkAlphaType srcAT, 281 const SkColorSpace* dst, 282 SkAlphaType dstAT); 283 SkColorSpaceXformSteps fSteps; 284 }; 285 286 static void BeginBlock(const KeyContext&, 287 PaintParamsKeyBuilder*, 288 PipelineDataGatherer*, 289 const ColorSpaceTransformData*); 290 }; 291 292 struct BlendModeBlock { 293 /** 294 * Blend mode blocks are used to blend a color attachment with the output of a shader. 295 */ 296 static void BeginBlock(const KeyContext&, 297 PaintParamsKeyBuilder*, 298 PipelineDataGatherer*, 299 SkBlendMode); 300 }; 301 302 struct PrimitiveBlendModeBlock { 303 /** 304 * Primitive blend mode blocks are used to blend a primitive color emitted by certain draw 305 * geometry calls (drawVertices, drawAtlas, etc.) with either the paint color or the output of 306 * another shader. Dst: primitiveColor Src: Paint color/shader output 307 */ 308 static void BeginBlock(const KeyContext&, 309 PaintParamsKeyBuilder*, 310 PipelineDataGatherer*, 311 SkBlendMode); 312 }; 313 314 struct RuntimeEffectBlock { 315 struct ShaderData { 316 // This ctor is used during pre-compilation when we don't have enough information to 317 // extract uniform data. 318 ShaderData(sk_sp<const SkRuntimeEffect> effect); 319 320 // This ctor is used when extracting information from PaintParams. 321 ShaderData(sk_sp<const SkRuntimeEffect> effect, 322 sk_sp<const SkData> uniforms); 323 324 bool operator==(const ShaderData& rhs) const; 325 bool operator!=(const ShaderData& rhs) const { return !(*this == rhs); } 326 327 // Runtime shader data. 328 sk_sp<const SkRuntimeEffect> fEffect; 329 sk_sp<const SkData> fUniforms; 330 }; 331 332 static void BeginBlock(const KeyContext&, 333 PaintParamsKeyBuilder*, 334 PipelineDataGatherer*, 335 const ShaderData&); 336 }; 337 338 } // namespace skgpu::graphite 339 340 #endif // skgpu_graphite_KeyHelpers_DEFINED 341