1 /* 2 * Copyright 2012 Google Inc. 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 SkGradientShaderPriv_DEFINED 9 #define SkGradientShaderPriv_DEFINED 10 11 #include "include/effects/SkGradientShader.h" 12 13 #include "include/core/SkMatrix.h" 14 #include "include/private/base/SkTArray.h" 15 #include "include/private/base/SkTemplates.h" 16 #include "src/core/SkVM.h" 17 #include "src/shaders/SkShaderBase.h" 18 19 #if defined(SK_GRAPHITE) 20 #include "src/gpu/graphite/KeyHelpers.h" 21 #endif 22 23 class SkArenaAlloc; 24 class SkColorSpace; 25 class SkRasterPipeline; 26 class SkReadBuffer; 27 class SkWriteBuffer; 28 29 class SkGradientShaderBase : public SkShaderBase { 30 public: 31 using Interpolation = SkGradientShader::Interpolation; 32 33 struct Descriptor { 34 Descriptor(); 35 ~Descriptor(); 36 37 Descriptor(const SkColor4f colors[], 38 sk_sp<SkColorSpace> colorSpace, 39 const SkScalar positions[], 40 int colorCount, 41 SkTileMode mode, 42 const Interpolation& interpolation); 43 44 const SkColor4f* fColors; 45 sk_sp<SkColorSpace> fColorSpace; 46 const SkScalar* fPositions; 47 int fColorCount; // length of fColors (and fPositions, if not nullptr) 48 SkTileMode fTileMode; 49 Interpolation fInterpolation; 50 }; 51 52 class DescriptorScope : public Descriptor { 53 public: DescriptorScope()54 DescriptorScope() {} 55 56 bool unflatten(SkReadBuffer&, SkMatrix* legacyLocalMatrix); 57 58 private: 59 SkSTArray<16, SkColor4f, true> fColorStorage; 60 SkSTArray<16, SkScalar , true> fPositionStorage; 61 }; 62 63 SkGradientShaderBase(const Descriptor& desc, const SkMatrix& ptsToUnit); 64 ~SkGradientShaderBase() override; 65 66 bool isOpaque() const override; 67 interpolateInPremul()68 bool interpolateInPremul() const { 69 return fInterpolation.fInPremul == SkGradientShader::Interpolation::InPremul::kYes; 70 } 71 getGradientMatrix()72 const SkMatrix& getGradientMatrix() const { return fPtsToUnit; } 73 74 static bool ValidGradient(const SkColor4f colors[], int count, SkTileMode tileMode, 75 const Interpolation& interpolation); 76 77 static sk_sp<SkShader> MakeDegenerateGradient(const SkColor4f colors[], const SkScalar pos[], 78 int colorCount, sk_sp<SkColorSpace> colorSpace, 79 SkTileMode mode); 80 81 struct ColorStopOptimizer { 82 ColorStopOptimizer(const SkColor4f* colors, const SkScalar* pos, int count, 83 SkTileMode mode); 84 85 const SkColor4f* fColors; 86 const SkScalar* fPos; 87 int fCount; 88 }; 89 90 // The default SkScalarNearlyZero threshold of .0024 is too big and causes regressions for svg 91 // gradients defined in the wild. 92 static constexpr SkScalar kDegenerateThreshold = SK_Scalar1 / (1 << 15); 93 94 protected: 95 void flatten(SkWriteBuffer&) const override; 96 97 void commonAsAGradient(GradientInfo*) const; 98 99 bool onAsLuminanceColor(SkColor*) const override; 100 101 bool appendStages(const SkStageRec&, const MatrixRec&) const override; 102 103 skvm::Color program(skvm::Builder*, 104 skvm::Coord device, 105 skvm::Coord local, 106 skvm::Color paint, 107 const MatrixRec&, 108 const SkColorInfo& dstCS, 109 skvm::Uniforms* uniforms, 110 SkArenaAlloc* alloc) const override; 111 112 virtual void appendGradientStages(SkArenaAlloc* alloc, SkRasterPipeline* tPipeline, 113 SkRasterPipeline* postPipeline) const = 0; 114 115 // Produce t from (x,y), modifying mask if it should be anything other than ~0. 116 virtual skvm::F32 transformT(skvm::Builder*, skvm::Uniforms*, 117 skvm::Coord coord, skvm::I32* mask) const = 0; 118 119 const SkMatrix fPtsToUnit; 120 SkTileMode fTileMode; 121 122 #if defined(SK_GRAPHITE) 123 static void MakeInterpolatedToDst(const skgpu::graphite::KeyContext&, 124 skgpu::graphite::PaintParamsKeyBuilder*, 125 skgpu::graphite::PipelineDataGatherer*, 126 const skgpu::graphite::GradientShaderBlocks::GradientData&, 127 const SkGradientShaderBase::Interpolation&, 128 SkColorSpace* intermediateCS); 129 #endif 130 131 public: 132 static void AppendGradientFillStages(SkRasterPipeline* p, 133 SkArenaAlloc* alloc, 134 const SkPMColor4f* colors, 135 const SkScalar* positions, 136 int count); 137 getPos(int i)138 SkScalar getPos(int i) const { 139 SkASSERT(i < fColorCount); 140 return fPositions ? fPositions[i] : SkIntToScalar(i) / (fColorCount - 1); 141 } 142 getLegacyColor(int i)143 SkColor getLegacyColor(int i) const { 144 SkASSERT(i < fColorCount); 145 return fColors[i].toSkColor(); 146 } 147 148 SkColor4f* fColors; // points into fStorage 149 SkScalar* fPositions; // points into fStorage, or nullptr 150 int fColorCount; // length of fColors (and fPositions, if not nullptr) 151 sk_sp<SkColorSpace> fColorSpace; // color space of gradient stops 152 Interpolation fInterpolation; 153 bool fFirstStopIsImplicit; 154 bool fLastStopIsImplicit; 155 colorsAreOpaque()156 bool colorsAreOpaque() const { return fColorsAreOpaque; } 157 getTileMode()158 SkTileMode getTileMode() const { return fTileMode; } 159 160 private: 161 // Reserve inline space for up to 4 stops. 162 inline static constexpr size_t kInlineStopCount = 4; 163 inline static constexpr size_t kInlineStorageSize = (sizeof(SkColor4f) + sizeof(SkScalar)) 164 * kInlineStopCount; 165 skia_private::AutoSTMalloc<kInlineStorageSize, uint8_t> fStorage; 166 167 bool fColorsAreOpaque; 168 169 using INHERITED = SkShaderBase; 170 }; 171 172 /////////////////////////////////////////////////////////////////////////////// 173 174 struct SkColor4fXformer { 175 SkColor4fXformer(const SkGradientShaderBase* shader, SkColorSpace* dst); 176 177 SkSTArray<4, SkPMColor4f, true> fColors; 178 sk_sp<SkColorSpace> fIntermediateColorSpace; 179 }; 180 181 struct SkColorConverter { 182 SkColorConverter(const SkColor* colors, int count); 183 184 SkSTArray<2, SkColor4f, true> fColors4f; 185 }; 186 187 void SkRegisterLinearGradientShaderFlattenable(); 188 void SkRegisterRadialGradientShaderFlattenable(); 189 void SkRegisterSweepGradientShaderFlattenable(); 190 void SkRegisterTwoPointConicalGradientShaderFlattenable(); 191 192 #endif 193