• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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