aboutsummaryrefslogtreecommitdiffhomepage
path: root/include/core/SkShader.h
diff options
context:
space:
mode:
authorGravatar Florin Malita <fmalita@chromium.org>2017-05-24 21:15:46 +0000
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2017-05-24 21:15:57 +0000
commitd93e11ceb427ff433d219081b74d10b8757d0b03 (patch)
treea893280c0cef7dacada35555281ce8951cad4552 /include/core/SkShader.h
parentffce079f4e0ca4ccb7f24aa647eee1de5feb6e02 (diff)
Revert "SkShaderBase"
This reverts commit 58a756435ca3700d9766a4580bb0771a9774f603. Reason for revert: g3, Android borkage. Original change's description: > SkShaderBase > > Introduce a private base class (SkShaderBase), to hide > implementation details from the public interface (SkShader). > > Change-Id: If3ec26ca6abc9da20e3f139c11fdc023bdd85176 > Reviewed-on: https://skia-review.googlesource.com/17241 > Commit-Queue: Florin Malita <fmalita@chromium.org> > Reviewed-by: Mike Reed <reed@google.com> > TBR=mtklein@google.com,fmalita@chromium.org,reed@google.com NOPRESUBMIT=true NOTREECHECKS=true NOTRY=true Change-Id: I32b012ee466dd006c074593f211f43ed602f1078 Reviewed-on: https://skia-review.googlesource.com/17845 Reviewed-by: Florin Malita <fmalita@chromium.org> Commit-Queue: Florin Malita <fmalita@chromium.org>
Diffstat (limited to 'include/core/SkShader.h')
-rw-r--r--include/core/SkShader.h305
1 files changed, 295 insertions, 10 deletions
diff --git a/include/core/SkShader.h b/include/core/SkShader.h
index 20898574e0..260306cfd4 100644
--- a/include/core/SkShader.h
+++ b/include/core/SkShader.h
@@ -40,6 +40,17 @@ class GrFragmentProcessor;
*/
class SK_API SkShader : public SkFlattenable {
public:
+ SkShader(const SkMatrix* localMatrix = NULL);
+ ~SkShader() override;
+
+ /**
+ * Returns the local matrix.
+ *
+ * FIXME: This can be incorrect for a Shader with its own local matrix
+ * that is also wrapped via CreateLocalMatrixShader.
+ */
+ const SkMatrix& getLocalMatrix() const { return fLocalMatrix; }
+
enum TileMode {
/** replicate the edge color if the shader draws outside of its
* original bounds
@@ -64,13 +75,23 @@ public:
kTileModeCount = kMirror_TileMode + 1
};
- /**
- * Returns the local matrix.
- *
- * FIXME: This can be incorrect for a Shader with its own local matrix
- * that is also wrapped via CreateLocalMatrixShader.
- */
- const SkMatrix& getLocalMatrix() const;
+ // override these in your subclass
+
+ enum Flags {
+ //!< set if all of the colors will be opaque
+ kOpaqueAlpha_Flag = 1 << 0,
+
+ /** set if the spans only vary in X (const in Y).
+ e.g. an Nx1 bitmap that is being tiled in Y, or a linear-gradient
+ that varies from left-to-right. This flag specifies this for
+ shadeSpan().
+ */
+ kConstInY32_Flag = 1 << 1,
+
+ /** hint for the blitter that 4f is the preferred shading mode.
+ */
+ kPrefers4f_Flag = 1 << 2,
+ };
/**
* Returns true if the shader is guaranteed to produce only opaque
@@ -80,13 +101,150 @@ public:
*/
virtual bool isOpaque() const { return false; }
+ /**
+ * Returns true if the shader is guaranteed to produce only a single color.
+ * Subclasses can override this to allow loop-hoisting optimization.
+ */
+ virtual bool isConstant() const { return false; }
+
+ /**
+ * ContextRec acts as a parameter bundle for creating Contexts.
+ */
+ struct ContextRec {
+ enum DstType {
+ kPMColor_DstType, // clients prefer shading into PMColor dest
+ kPM4f_DstType, // clients prefer shading into PM4f dest
+ };
+
+ ContextRec(const SkPaint& paint, const SkMatrix& matrix, const SkMatrix* localM,
+ DstType dstType, SkColorSpace* dstColorSpace)
+ : fPaint(&paint)
+ , fMatrix(&matrix)
+ , fLocalMatrix(localM)
+ , fPreferredDstType(dstType)
+ , fDstColorSpace(dstColorSpace) {}
+
+ const SkPaint* fPaint; // the current paint associated with the draw
+ const SkMatrix* fMatrix; // the current matrix in the canvas
+ const SkMatrix* fLocalMatrix; // optional local matrix
+ const DstType fPreferredDstType; // the "natural" client dest type
+ SkColorSpace* fDstColorSpace; // the color space of the dest surface (if any)
+ };
+
+ class Context : public ::SkNoncopyable {
+ public:
+ Context(const SkShader& shader, const ContextRec&);
+
+ virtual ~Context();
+
+ /**
+ * Called sometimes before drawing with this shader. Return the type of
+ * alpha your shader will return. The default implementation returns 0.
+ * Your subclass should override if it can (even sometimes) report a
+ * non-zero value, since that will enable various blitters to perform
+ * faster.
+ */
+ virtual uint32_t getFlags() const { return 0; }
+
+ /**
+ * Called for each span of the object being drawn. Your subclass should
+ * set the appropriate colors (with premultiplied alpha) that correspond
+ * to the specified device coordinates.
+ */
+ virtual void shadeSpan(int x, int y, SkPMColor[], int count) = 0;
+
+ virtual void shadeSpan4f(int x, int y, SkPM4f[], int count);
+
+ struct BlitState;
+ typedef void (*BlitBW)(BlitState*,
+ int x, int y, const SkPixmap&, int count);
+ typedef void (*BlitAA)(BlitState*,
+ int x, int y, const SkPixmap&, int count, const SkAlpha[]);
+
+ struct BlitState {
+ // inputs
+ Context* fCtx;
+ SkBlendMode fMode;
+
+ // outputs
+ enum { N = 2 };
+ void* fStorage[N];
+ BlitBW fBlitBW;
+ BlitAA fBlitAA;
+ };
+
+ // Returns true if one or more of the blitprocs are set in the BlitState
+ bool chooseBlitProcs(const SkImageInfo& info, BlitState* state) {
+ state->fBlitBW = nullptr;
+ state->fBlitAA = nullptr;
+ if (this->onChooseBlitProcs(info, state)) {
+ SkASSERT(state->fBlitBW || state->fBlitAA);
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * The const void* ctx is only const because all the implementations are const.
+ * This can be changed to non-const if a new shade proc needs to change the ctx.
+ */
+ typedef void (*ShadeProc)(const void* ctx, int x, int y, SkPMColor[], int count);
+ virtual ShadeProc asAShadeProc(void** ctx);
+
+ /**
+ * Similar to shadeSpan, but only returns the alpha-channel for a span.
+ * The default implementation calls shadeSpan() and then extracts the alpha
+ * values from the returned colors.
+ */
+ virtual void shadeSpanAlpha(int x, int y, uint8_t alpha[], int count);
+
+ // Notification from blitter::blitMask in case we need to see the non-alpha channels
+ virtual void set3DMask(const SkMask*) {}
+
+ protected:
+ // Reference to shader, so we don't have to dupe information.
+ const SkShader& fShader;
+
+ enum MatrixClass {
+ kLinear_MatrixClass, // no perspective
+ kFixedStepInX_MatrixClass, // fast perspective, need to call fixedStepInX() each
+ // scanline
+ kPerspective_MatrixClass // slow perspective, need to mappoints each pixel
+ };
+ static MatrixClass ComputeMatrixClass(const SkMatrix&);
+
+ uint8_t getPaintAlpha() const { return fPaintAlpha; }
+ const SkMatrix& getTotalInverse() const { return fTotalInverse; }
+ MatrixClass getInverseClass() const { return (MatrixClass)fTotalInverseClass; }
+ const SkMatrix& getCTM() const { return fCTM; }
+
+ virtual bool onChooseBlitProcs(const SkImageInfo&, BlitState*) { return false; }
+
+ private:
+ SkMatrix fCTM;
+ SkMatrix fTotalInverse;
+ uint8_t fPaintAlpha;
+ uint8_t fTotalInverseClass;
+
+ typedef SkNoncopyable INHERITED;
+ };
+
+ /**
+ * Make a context using the memory provided by the arena.
+ *
+ * @return pointer to context or nullptr if can't be created
+ */
+ Context* makeContext(const ContextRec&, SkArenaAlloc*) const;
+
#ifdef SK_SUPPORT_LEGACY_SHADER_ISABITMAP
/**
* Returns true if this shader is just a bitmap, and if not null, returns the bitmap,
* localMatrix, and tilemodes. If this is not a bitmap, returns false and ignores the
* out-parameters.
*/
- bool isABitmap(SkBitmap* outTexture, SkMatrix* outMatrix, TileMode xy[2]) const;
+ bool isABitmap(SkBitmap* outTexture, SkMatrix* outMatrix, TileMode xy[2]) const {
+ return this->onIsABitmap(outTexture, outMatrix, xy);
+ }
bool isABitmap() const {
return this->isABitmap(nullptr, nullptr, nullptr);
@@ -97,7 +255,9 @@ public:
* Iff this shader is backed by a single SkImage, return its ptr (the caller must ref this
* if they want to keep it longer than the lifetime of the shader). If not, return nullptr.
*/
- SkImage* isAImage(SkMatrix* localMatrix, TileMode xy[2]) const;
+ SkImage* isAImage(SkMatrix* localMatrix, TileMode xy[2]) const {
+ return this->onIsAImage(localMatrix, xy);
+ }
bool isAImage() const {
return this->isAImage(nullptr, nullptr) != nullptr;
@@ -157,6 +317,68 @@ public:
virtual GradientType asAGradient(GradientInfo* info) const;
+ /**
+ * If the shader subclass is composed of two shaders, return true, and if rec is not NULL,
+ * fill it out with info about the shader.
+ *
+ * These are bare pointers; the ownership and reference count are unchanged.
+ */
+
+ struct ComposeRec {
+ const SkShader* fShaderA;
+ const SkShader* fShaderB;
+ SkBlendMode fBlendMode;
+ };
+
+ virtual bool asACompose(ComposeRec*) const { return false; }
+
+#if SK_SUPPORT_GPU
+ struct AsFPArgs {
+ AsFPArgs() {}
+ AsFPArgs(GrContext* context,
+ const SkMatrix* viewMatrix,
+ const SkMatrix* localMatrix,
+ SkFilterQuality filterQuality,
+ SkColorSpace* dstColorSpace)
+ : fContext(context)
+ , fViewMatrix(viewMatrix)
+ , fLocalMatrix(localMatrix)
+ , fFilterQuality(filterQuality)
+ , fDstColorSpace(dstColorSpace) {}
+
+ GrContext* fContext;
+ const SkMatrix* fViewMatrix;
+ const SkMatrix* fLocalMatrix;
+ SkFilterQuality fFilterQuality;
+ SkColorSpace* fDstColorSpace;
+ };
+
+ /**
+ * Returns a GrFragmentProcessor that implements the shader for the GPU backend. NULL is
+ * returned if there is no GPU implementation.
+ *
+ * The GPU device does not call SkShader::createContext(), instead we pass the view matrix,
+ * local matrix, and filter quality directly.
+ *
+ * The GrContext may be used by the to create textures that are required by the returned
+ * processor.
+ *
+ * The returned GrFragmentProcessor should expect an unpremultiplied input color and
+ * produce a premultiplied output.
+ */
+ virtual sk_sp<GrFragmentProcessor> asFragmentProcessor(const AsFPArgs&) const;
+#endif
+
+ /**
+ * If the shader can represent its "average" luminance in a single color, return true and
+ * if color is not NULL, return that color. If it cannot, return false and ignore the color
+ * parameter.
+ *
+ * Note: if this returns true, the returned color will always be opaque, as only the RGB
+ * components are used to compute luminance.
+ */
+ bool asLuminanceColor(SkColor*) const;
+
//////////////////////////////////////////////////////////////////////////
// Methods to create combinations or variants of shaders
@@ -232,10 +454,73 @@ public:
static sk_sp<SkShader> MakePictureShader(sk_sp<SkPicture> src, TileMode tmx, TileMode tmy,
const SkMatrix* localMatrix, const SkRect* tile);
+ /**
+ * If this shader can be represented by another shader + a localMatrix, return that shader and
+ * the localMatrix. If not, return nullptr and ignore the localMatrix parameter.
+ */
+ virtual sk_sp<SkShader> makeAsALocalMatrixShader(SkMatrix* localMatrix) const;
+
+ SK_TO_STRING_VIRT()
+ SK_DEFINE_FLATTENABLE_TYPE(SkShader)
+ SK_DECLARE_FLATTENABLE_REGISTRAR_GROUP()
+
+ bool appendStages(SkRasterPipeline*, SkColorSpace* dstCS, SkArenaAlloc*,
+ const SkMatrix& ctm, const SkPaint&, const SkMatrix* localM=nullptr) const;
+
protected:
- SkShader() = default;
+ void flatten(SkWriteBuffer&) const override;
+
+ bool computeTotalInverse(const SkMatrix& ctm,
+ const SkMatrix* outerLocalMatrix,
+ SkMatrix* totalInverse) const;
+
+ /**
+ * Specialize creating a SkShader context using the supplied allocator.
+ * @return pointer to context owned by the arena allocator.
+ */
+ virtual Context* onMakeContext(const ContextRec&, SkArenaAlloc*) const {
+ return nullptr;
+ }
+
+ virtual bool onAsLuminanceColor(SkColor*) const {
+ return false;
+ }
+
+#ifdef SK_SUPPORT_LEGACY_SHADER_ISABITMAP
+ virtual bool onIsABitmap(SkBitmap*, SkMatrix*, TileMode[2]) const {
+ return false;
+ }
+#endif
+
+ virtual SkImage* onIsAImage(SkMatrix*, TileMode[2]) const {
+ return nullptr;
+ }
+
+ /**
+ * Returns a shader transformed into a new color space via the |xformer|.
+ */
+ sk_sp<SkShader> makeColorSpace(SkColorSpaceXformer* xformer) const {
+ return this->onMakeColorSpace(xformer);
+ }
+ virtual sk_sp<SkShader> onMakeColorSpace(SkColorSpaceXformer*) const {
+ return sk_ref_sp(const_cast<SkShader*>(this));
+ }
+
+ virtual bool isRasterPipelineOnly() const { return false; }
private:
+ virtual bool onAppendStages(SkRasterPipeline*, SkColorSpace* dstCS, SkArenaAlloc*,
+ const SkMatrix&, const SkPaint&, const SkMatrix* localM) const;
+
+ // This is essentially const, but not officially so it can be modified in constructors.
+ SkMatrix fLocalMatrix;
+
+ friend class SkLocalMatrixShader; // sets fLocalMatrix in SkReadBuffer constructor
+ friend class SkBitmapProcLegacyShader; // calls computeTotalInverse()
+ friend class SkColorSpaceXformer; // calls makeColorSpace()
+ friend class SkBlitter; // calls isRasterPipelineOnly()
+ friend class SkComposeShader; // calls isRasterPipelineOnly()
+
typedef SkFlattenable INHERITED;
};