/* * Copyright 2022 Google LLC * * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #ifndef skgpu_graphite_KeyHelpers_DEFINED #define skgpu_graphite_KeyHelpers_DEFINED #include "include/core/SkBlendMode.h" #include "include/core/SkM44.h" #include "include/core/SkSamplingOptions.h" #include "include/core/SkShader.h" #include "include/core/SkSpan.h" #include "include/core/SkTileMode.h" #include "include/effects/SkGradientShader.h" #include "include/gpu/graphite/Context.h" #include "include/private/SkColorData.h" #include "src/core/SkColorSpaceXformSteps.h" #include "src/gpu/graphite/TextureProxy.h" #include "src/shaders/SkShaderBase.h" class SkData; class SkRuntimeEffect; namespace skgpu::graphite { class KeyContext; class PaintParamsKeyBuilder; class PipelineDataGatherer; class UniquePaintParamsID; enum class ReadSwizzle; /** * The KeyHelpers can be used to manually construct an SkPaintParamsKey. * * TODO: If we restructure how the keys are made, we can utilize a single block type for the * different blend blocks outlined below. The different Src/Dst pairings could instead be encoded * as parent-child relationships. */ struct PassthroughShaderBlock { static void BeginBlock(const KeyContext&, PaintParamsKeyBuilder*, PipelineDataGatherer*); }; struct PassthroughBlenderBlock { static void BeginBlock(const KeyContext&, PaintParamsKeyBuilder*, PipelineDataGatherer*); }; struct SolidColorShaderBlock { static void BeginBlock(const KeyContext&, PaintParamsKeyBuilder*, PipelineDataGatherer*, const SkPMColor4f&); }; struct GradientShaderBlocks { struct GradientData { // TODO: For the sprint we only support 8 stops in the gradients static constexpr int kMaxStops = 8; // This ctor is used during pre-compilation when we don't have enough information to // extract uniform data. However, we must be able to provide enough data to make all the // relevant decisions about which code snippets to use. GradientData(SkShaderBase::GradientType, int numStops); // This ctor is used when extracting information from PaintParams. It must provide // enough data to generate the uniform data the selected code snippet will require. GradientData(SkShaderBase::GradientType, SkPoint point0, SkPoint point1, float radius0, float radius1, float bias, float scale, SkTileMode, int numStops, const SkPMColor4f* colors, float* offsets, const SkGradientShader::Interpolation&); bool operator==(const GradientData& rhs) const { return fType == rhs.fType && fPoints[0] == rhs.fPoints[0] && fPoints[1] == rhs.fPoints[1] && fRadii[0] == rhs.fRadii[0] && fRadii[1] == rhs.fRadii[1] && fBias == rhs.fBias && fScale == rhs.fScale && fTM == rhs.fTM && fNumStops == rhs.fNumStops && !memcmp(fColors, rhs.fColors, sizeof(fColors)) && !memcmp(fOffsets, rhs.fOffsets, sizeof(fOffsets)); } bool operator!=(const GradientData& rhs) const { return !(*this == rhs); } // Layout options. SkShaderBase::GradientType fType; SkPoint fPoints[2]; float fRadii[2]; // Layout options for sweep gradient. float fBias; float fScale; SkTileMode fTM; int fNumStops; SkPMColor4f fColors[kMaxStops]; float fOffsets[kMaxStops]; SkGradientShader::Interpolation fInterpolation; }; static void BeginBlock(const KeyContext&, PaintParamsKeyBuilder*, PipelineDataGatherer*, const GradientData&); }; struct LocalMatrixShaderBlock { struct LMShaderData { LMShaderData(const SkMatrix& localMatrix) : fLocalMatrix(localMatrix) { } const SkM44 fLocalMatrix; }; static void BeginBlock(const KeyContext&, PaintParamsKeyBuilder*, PipelineDataGatherer*, const LMShaderData*); }; struct ImageShaderBlock { struct ImageData { ImageData(const SkSamplingOptions& sampling, SkTileMode tileModeX, SkTileMode tileModeY, SkRect subset, ReadSwizzle readSwizzle); SkSamplingOptions fSampling; SkTileMode fTileModes[2]; SkRect fSubset; ReadSwizzle fReadSwizzle; SkColorSpaceXformSteps fSteps; // TODO: Currently this is only filled in when we're generating the key from an actual // SkImageShader. In the pre-compile case we will need to create a Graphite promise // image which holds the appropriate data. sk_sp fTextureProxy; }; // The gatherer and imageData should be null or non-null together static void BeginBlock(const KeyContext&, PaintParamsKeyBuilder*, PipelineDataGatherer*, const ImageData*); }; struct PorterDuffBlendShaderBlock { struct PorterDuffBlendShaderData { SkSpan fPorterDuffConstants; }; static void BeginBlock(const KeyContext&, PaintParamsKeyBuilder*, PipelineDataGatherer*, const PorterDuffBlendShaderData&); }; struct BlendShaderBlock { /** * Blend shader blocks are used to blend the output of two shaders. */ struct BlendShaderData { SkBlendMode fBM; }; static void BeginBlock(const KeyContext&, PaintParamsKeyBuilder*, PipelineDataGatherer*, const BlendShaderData&); }; struct ColorFilterShaderBlock { static void BeginBlock(const KeyContext&, PaintParamsKeyBuilder*, PipelineDataGatherer*); }; struct MatrixColorFilterBlock { struct MatrixColorFilterData { MatrixColorFilterData(const float matrix[20], bool inHSLA) : fMatrix(matrix[ 0], matrix[ 1], matrix[ 2], matrix[ 3], matrix[ 5], matrix[ 6], matrix[ 7], matrix[ 8], matrix[10], matrix[11], matrix[12], matrix[13], matrix[15], matrix[16], matrix[17], matrix[18]) , fTranslate{matrix[4], matrix[9], matrix[14], matrix[19]} , fInHSLA(inHSLA) { } SkM44 fMatrix; SkV4 fTranslate; bool fInHSLA; }; // The gatherer and matrixCFData should be null or non-null together static void BeginBlock(const KeyContext&, PaintParamsKeyBuilder*, PipelineDataGatherer*, const MatrixColorFilterData*); }; struct BlendColorFilterBlock { /** * Blend color filter blocks are used to blend the output of a shader with a color uniform. */ struct BlendColorFilterData { BlendColorFilterData(SkBlendMode blendMode, const SkPMColor4f& srcColor) : fBlendMode(blendMode) , fSrcColor(srcColor) { } SkBlendMode fBlendMode; SkPMColor4f fSrcColor; }; static void BeginBlock(const KeyContext&, PaintParamsKeyBuilder*, PipelineDataGatherer*, const BlendColorFilterData*); }; struct ComposeColorFilterBlock { static void BeginBlock(const KeyContext&, PaintParamsKeyBuilder*, PipelineDataGatherer*); }; struct TableColorFilterBlock { struct TableColorFilterData { TableColorFilterData(); sk_sp fTextureProxy; }; static void BeginBlock(const KeyContext&, PaintParamsKeyBuilder*, PipelineDataGatherer*, const TableColorFilterData&); }; struct GaussianColorFilterBlock { static void BeginBlock(const KeyContext&, PaintParamsKeyBuilder*, PipelineDataGatherer*); }; struct ColorSpaceTransformBlock { struct ColorSpaceTransformData { ColorSpaceTransformData(const SkColorSpace* src, SkAlphaType srcAT, const SkColorSpace* dst, SkAlphaType dstAT); SkColorSpaceXformSteps fSteps; }; static void BeginBlock(const KeyContext&, PaintParamsKeyBuilder*, PipelineDataGatherer*, const ColorSpaceTransformData*); }; struct BlendModeBlock { /** * Blend mode blocks are used to blend a color attachment with the output of a shader. */ static void BeginBlock(const KeyContext&, PaintParamsKeyBuilder*, PipelineDataGatherer*, SkBlendMode); }; struct PrimitiveBlendModeBlock { /** * Primitive blend mode blocks are used to blend a primitive color emitted by certain draw * geometry calls (drawVertices, drawAtlas, etc.) with either the paint color or the output of * another shader. Dst: primitiveColor Src: Paint color/shader output */ static void BeginBlock(const KeyContext&, PaintParamsKeyBuilder*, PipelineDataGatherer*, SkBlendMode); }; struct RuntimeEffectBlock { struct ShaderData { // This ctor is used during pre-compilation when we don't have enough information to // extract uniform data. ShaderData(sk_sp effect); // This ctor is used when extracting information from PaintParams. ShaderData(sk_sp effect, sk_sp uniforms); bool operator==(const ShaderData& rhs) const; bool operator!=(const ShaderData& rhs) const { return !(*this == rhs); } // Runtime shader data. sk_sp fEffect; sk_sp fUniforms; }; static void BeginBlock(const KeyContext&, PaintParamsKeyBuilder*, PipelineDataGatherer*, const ShaderData&); }; } // namespace skgpu::graphite #endif // skgpu_graphite_KeyHelpers_DEFINED