diff options
author | Florin Malita <fmalita@chromium.org> | 2017-05-24 21:15:46 +0000 |
---|---|---|
committer | Skia Commit-Bot <skia-commit-bot@chromium.org> | 2017-05-24 21:15:57 +0000 |
commit | d93e11ceb427ff433d219081b74d10b8757d0b03 (patch) | |
tree | a893280c0cef7dacada35555281ce8951cad4552 /include/core/SkShader.h | |
parent | ffce079f4e0ca4ccb7f24aa647eee1de5feb6e02 (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.h | 305 |
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; }; |