blob: 85c08fe75d2fc5bbd16b470ad3bb52ef8f946c98 [file] [log] [blame]
Florin Malita4aed1382017-05-25 10:38:07 -04001/*
2 * Copyright 2017 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 SkShaderBase_DEFINED
9#define SkShaderBase_DEFINED
10
11#include "SkFilterQuality.h"
12#include "SkMatrix.h"
13#include "SkShader.h"
14
15class GrContext;
Brian Salomon4cbb6e62017-10-25 15:12:19 -040016class GrColorSpaceInfo;
Florin Malita4aed1382017-05-25 10:38:07 -040017class GrFragmentProcessor;
18class SkArenaAlloc;
19class SkColorSpace;
20class SkColorSpaceXformer;
21class SkImage;
22struct SkImageInfo;
23class SkPaint;
24class SkRasterPipeline;
25
Florin Malita95c993c2017-05-26 09:44:10 -040026class SkShaderBase : public SkShader {
Florin Malita4aed1382017-05-25 10:38:07 -040027public:
Florin Malita4aed1382017-05-25 10:38:07 -040028 ~SkShaderBase() override;
29
30 /**
31 * Returns true if the shader is guaranteed to produce only a single color.
32 * Subclasses can override this to allow loop-hoisting optimization.
33 */
34 virtual bool isConstant() const { return false; }
35
36 const SkMatrix& getLocalMatrix() const { return fLocalMatrix; }
37
38 enum Flags {
39 //!< set if all of the colors will be opaque
40 kOpaqueAlpha_Flag = 1 << 0,
41
42 /** set if the spans only vary in X (const in Y).
43 e.g. an Nx1 bitmap that is being tiled in Y, or a linear-gradient
44 that varies from left-to-right. This flag specifies this for
45 shadeSpan().
46 */
47 kConstInY32_Flag = 1 << 1,
48
49 /** hint for the blitter that 4f is the preferred shading mode.
50 */
51 kPrefers4f_Flag = 1 << 2,
52 };
53
54 /**
55 * ContextRec acts as a parameter bundle for creating Contexts.
56 */
57 struct ContextRec {
58 enum DstType {
59 kPMColor_DstType, // clients prefer shading into PMColor dest
60 kPM4f_DstType, // clients prefer shading into PM4f dest
61 };
62
63 ContextRec(const SkPaint& paint, const SkMatrix& matrix, const SkMatrix* localM,
64 DstType dstType, SkColorSpace* dstColorSpace)
65 : fPaint(&paint)
66 , fMatrix(&matrix)
67 , fLocalMatrix(localM)
68 , fPreferredDstType(dstType)
69 , fDstColorSpace(dstColorSpace) {}
70
71 const SkPaint* fPaint; // the current paint associated with the draw
72 const SkMatrix* fMatrix; // the current matrix in the canvas
73 const SkMatrix* fLocalMatrix; // optional local matrix
74 const DstType fPreferredDstType; // the "natural" client dest type
75 SkColorSpace* fDstColorSpace; // the color space of the dest surface (if any)
76 };
77
78 class Context : public ::SkNoncopyable {
79 public:
80 Context(const SkShaderBase& shader, const ContextRec&);
81
82 virtual ~Context();
83
84 /**
85 * Called sometimes before drawing with this shader. Return the type of
86 * alpha your shader will return. The default implementation returns 0.
87 * Your subclass should override if it can (even sometimes) report a
88 * non-zero value, since that will enable various blitters to perform
89 * faster.
90 */
91 virtual uint32_t getFlags() const { return 0; }
92
93 /**
94 * Called for each span of the object being drawn. Your subclass should
95 * set the appropriate colors (with premultiplied alpha) that correspond
96 * to the specified device coordinates.
97 */
98 virtual void shadeSpan(int x, int y, SkPMColor[], int count) = 0;
99
100 virtual void shadeSpan4f(int x, int y, SkPM4f[], int count);
101
Florin Malita4aed1382017-05-25 10:38:07 -0400102 // Notification from blitter::blitMask in case we need to see the non-alpha channels
103 virtual void set3DMask(const SkMask*) {}
104
105 protected:
106 // Reference to shader, so we don't have to dupe information.
107 const SkShaderBase& fShader;
108
Florin Malita4aed1382017-05-25 10:38:07 -0400109 uint8_t getPaintAlpha() const { return fPaintAlpha; }
110 const SkMatrix& getTotalInverse() const { return fTotalInverse; }
Florin Malita4aed1382017-05-25 10:38:07 -0400111 const SkMatrix& getCTM() const { return fCTM; }
112
Florin Malita4aed1382017-05-25 10:38:07 -0400113 private:
114 SkMatrix fCTM;
115 SkMatrix fTotalInverse;
116 uint8_t fPaintAlpha;
Florin Malita4aed1382017-05-25 10:38:07 -0400117
118 typedef SkNoncopyable INHERITED;
119 };
120
121 /**
122 * Make a context using the memory provided by the arena.
123 *
124 * @return pointer to context or nullptr if can't be created
125 */
126 Context* makeContext(const ContextRec&, SkArenaAlloc*) const;
127
Florin Malita47e55a52017-06-06 12:26:54 -0400128 /**
129 * Shaders may opt-in for burst mode, if they can operate
130 * significantly more efficiently in that mode.
131 *
132 * Burst mode is prioritized in SkRasterPipelineBlitter over
133 * regular (appendStages) pipeline operation.
134 */
135 Context* makeBurstPipelineContext(const ContextRec&, SkArenaAlloc*) const;
136
Florin Malita4aed1382017-05-25 10:38:07 -0400137#if SK_SUPPORT_GPU
138 struct AsFPArgs {
139 AsFPArgs() {}
140 AsFPArgs(GrContext* context,
141 const SkMatrix* viewMatrix,
142 const SkMatrix* localMatrix,
143 SkFilterQuality filterQuality,
Brian Salomon4cbb6e62017-10-25 15:12:19 -0400144 const GrColorSpaceInfo* dstColorSpaceInfo)
145 : fContext(context)
146 , fViewMatrix(viewMatrix)
147 , fLocalMatrix(localMatrix)
148 , fFilterQuality(filterQuality)
149 , fDstColorSpaceInfo(dstColorSpaceInfo) {}
Florin Malita4aed1382017-05-25 10:38:07 -0400150
Brian Salomon4cbb6e62017-10-25 15:12:19 -0400151 GrContext* fContext;
152 const SkMatrix* fViewMatrix;
153 const SkMatrix* fLocalMatrix;
154 SkFilterQuality fFilterQuality;
155 const GrColorSpaceInfo* fDstColorSpaceInfo;
Florin Malita4aed1382017-05-25 10:38:07 -0400156 };
157
158 /**
159 * Returns a GrFragmentProcessor that implements the shader for the GPU backend. NULL is
160 * returned if there is no GPU implementation.
161 *
162 * The GPU device does not call SkShader::createContext(), instead we pass the view matrix,
163 * local matrix, and filter quality directly.
164 *
165 * The GrContext may be used by the to create textures that are required by the returned
166 * processor.
167 *
168 * The returned GrFragmentProcessor should expect an unpremultiplied input color and
169 * produce a premultiplied output.
170 */
Brian Salomonaff329b2017-08-11 09:40:37 -0400171 virtual std::unique_ptr<GrFragmentProcessor> asFragmentProcessor(const AsFPArgs&) const;
Florin Malita4aed1382017-05-25 10:38:07 -0400172#endif
173
174 /**
175 * If the shader can represent its "average" luminance in a single color, return true and
176 * if color is not NULL, return that color. If it cannot, return false and ignore the color
177 * parameter.
178 *
179 * Note: if this returns true, the returned color will always be opaque, as only the RGB
180 * components are used to compute luminance.
181 */
182 bool asLuminanceColor(SkColor*) const;
183
184 /**
185 * Returns a shader transformed into a new color space via the |xformer|.
186 */
187 sk_sp<SkShader> makeColorSpace(SkColorSpaceXformer* xformer) const {
188 return this->onMakeColorSpace(xformer);
189 }
190
Mike Reed34042072017-08-08 16:29:22 -0400191 bool isRasterPipelineOnly(const SkMatrix& ctm) const {
Florin Malita5769dd22017-07-12 13:31:25 -0400192 // We always use RP when perspective is present.
Mike Reed34042072017-08-08 16:29:22 -0400193 return ctm.hasPerspective() || fLocalMatrix.hasPerspective()
194 || this->onIsRasterPipelineOnly(ctm);
Florin Malita5769dd22017-07-12 13:31:25 -0400195 }
Florin Malita4aed1382017-05-25 10:38:07 -0400196
Mike Reed1d8c42e2017-08-29 14:58:19 -0400197 struct StageRec {
198 SkRasterPipeline* fPipeline;
199 SkArenaAlloc* fAlloc;
200 SkColorSpace* fDstCS; // may be nullptr
201 const SkPaint& fPaint;
202 const SkMatrix* fLocalM; // may be nullptr
203 SkMatrix fCTM;
204 };
205
Mike Reed6867eee2017-06-02 13:25:15 -0400206 // If this returns false, then we draw nothing (do not fall back to shader context)
Mike Reed1d8c42e2017-08-29 14:58:19 -0400207 bool appendStages(const StageRec&) const;
Florin Malita4aed1382017-05-25 10:38:07 -0400208
209 bool computeTotalInverse(const SkMatrix& ctm,
210 const SkMatrix* outerLocalMatrix,
211 SkMatrix* totalInverse) const;
212
213#ifdef SK_SUPPORT_LEGACY_SHADER_ISABITMAP
214 virtual bool onIsABitmap(SkBitmap*, SkMatrix*, TileMode[2]) const {
215 return false;
216 }
217#endif
218
219 virtual SkImage* onIsAImage(SkMatrix*, TileMode[2]) const {
220 return nullptr;
221 }
222
223 SK_TO_STRING_VIRT()
224
225 SK_DEFINE_FLATTENABLE_TYPE(SkShaderBase)
226 SK_DECLARE_FLATTENABLE_REGISTRAR_GROUP()
227
228protected:
Florin Malitaf7beee72017-05-26 12:54:32 -0400229 SkShaderBase(const SkMatrix* localMatrix = nullptr);
230
Florin Malita4aed1382017-05-25 10:38:07 -0400231 void flatten(SkWriteBuffer&) const override;
232
233 /**
234 * Specialize creating a SkShader context using the supplied allocator.
235 * @return pointer to context owned by the arena allocator.
236 */
237 virtual Context* onMakeContext(const ContextRec&, SkArenaAlloc*) const {
238 return nullptr;
239 }
240
Florin Malita47e55a52017-06-06 12:26:54 -0400241 /**
242 * Overriden by shaders which prefer burst mode.
243 */
244 virtual Context* onMakeBurstPipelineContext(const ContextRec&, SkArenaAlloc*) const {
245 return nullptr;
246 }
247
Florin Malita4aed1382017-05-25 10:38:07 -0400248 virtual bool onAsLuminanceColor(SkColor*) const {
249 return false;
250 }
251
252 virtual sk_sp<SkShader> onMakeColorSpace(SkColorSpaceXformer*) const {
253 return sk_ref_sp(const_cast<SkShaderBase*>(this));
254 }
255
Mike Reed6867eee2017-06-02 13:25:15 -0400256 // Default impl creates shadercontext and calls that (not very efficient)
Mike Reed1d8c42e2017-08-29 14:58:19 -0400257 virtual bool onAppendStages(const StageRec&) const;
Florin Malita4aed1382017-05-25 10:38:07 -0400258
Mike Reed34042072017-08-08 16:29:22 -0400259 virtual bool onIsRasterPipelineOnly(const SkMatrix& ctm) const { return false; }
Florin Malita5769dd22017-07-12 13:31:25 -0400260
Florin Malita4aed1382017-05-25 10:38:07 -0400261private:
262 // This is essentially const, but not officially so it can be modified in constructors.
263 SkMatrix fLocalMatrix;
264
265 typedef SkShader INHERITED;
266};
267
268inline SkShaderBase* as_SB(SkShader* shader) {
269 return static_cast<SkShaderBase*>(shader);
270}
271
272inline const SkShaderBase* as_SB(const SkShader* shader) {
273 return static_cast<const SkShaderBase*>(shader);
274}
275
276inline const SkShaderBase* as_SB(const sk_sp<SkShader>& shader) {
277 return static_cast<SkShaderBase*>(shader.get());
278}
279
280#endif // SkShaderBase_DEFINED