diff options
author | commit-bot@chromium.org <commit-bot@chromium.org@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2014-04-17 21:09:49 +0000 |
---|---|---|
committer | commit-bot@chromium.org <commit-bot@chromium.org@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2014-04-17 21:09:49 +0000 |
commit | 53783b026a00683c1fb504127c3398dabb61ea73 (patch) | |
tree | 0dd91705720040c78d85b26e1cd3c082fa822db2 | |
parent | ec2d8b37b069a9871cf2228f1ff83f8d70628cab (diff) |
Revert of Extract most of the mutable state of SkShader into a separate Context object. (https://codereview.chromium.org/207683004/)
Reason for revert:
Causing memory leaks in Chromium.
Original issue's description:
> Extract most of the mutable state of SkShader into a separate Context object.
>
> SkShader currently stores some state during draw calls via setContext(...).
> Move that mutable state into a separate SkShader::Context class that is
> constructed on demand for the duration of the draw.
>
> Calls to setContext() are replaced with createContext() which returns a context
> corresponding to the shader object or NULL if the parameters to createContext
> are invalid.
>
> TEST=out/Debug/dm
> BUG=skia:1976
>
> Committed: http://code.google.com/p/skia/source/detail?r=14216
R=scroggo@google.com, skyostil@chromium.org, tomhudson@chromium.org, senorblanco@chromium.org, reed@google.com, dominikg@chromium.org
TBR=dominikg@chromium.org, reed@google.com, scroggo@google.com, senorblanco@chromium.org, skyostil@chromium.org, tomhudson@chromium.org
NOTREECHECKS=true
NOTRY=true
BUG=skia:1976
Author: bungeman@google.com
Review URL: https://codereview.chromium.org/241283003
git-svn-id: http://skia.googlecode.com/svn/trunk@14247 2bbb7eff-a529-9590-31e7-b0007b416f81
38 files changed, 997 insertions, 1669 deletions
diff --git a/include/core/SkColorShader.h b/include/core/SkColorShader.h index 56e5add4a3..975156c0eb 100644 --- a/include/core/SkColorShader.h +++ b/include/core/SkColorShader.h @@ -30,35 +30,16 @@ public: */ SkColorShader(SkColor c); - virtual bool isOpaque() const SK_OVERRIDE; - - virtual SkShader::Context* createContext(const SkBitmap& device, - const SkPaint& paint, - const SkMatrix& matrix, - void* storage) const SK_OVERRIDE; - - virtual size_t contextSize() const SK_OVERRIDE { - return sizeof(ColorShaderContext); - } - - class ColorShaderContext : public SkShader::Context { - public: - ColorShaderContext(const SkColorShader& shader, const SkBitmap& device, - const SkPaint& paint, const SkMatrix& matrix); + virtual ~SkColorShader(); - virtual uint32_t getFlags() const SK_OVERRIDE; - virtual uint8_t getSpan16Alpha() const SK_OVERRIDE; - virtual void shadeSpan(int x, int y, SkPMColor span[], int count) SK_OVERRIDE; - virtual void shadeSpan16(int x, int y, uint16_t span[], int count) SK_OVERRIDE; - virtual void shadeSpanAlpha(int x, int y, uint8_t alpha[], int count) SK_OVERRIDE; - - private: - SkPMColor fPMColor; - uint32_t fFlags; - uint16_t fColor16; - - typedef SkShader::Context INHERITED; - }; + virtual uint32_t getFlags() SK_OVERRIDE; + virtual uint8_t getSpan16Alpha() const SK_OVERRIDE; + virtual bool isOpaque() const SK_OVERRIDE; + virtual bool setContext(const SkBitmap& device, const SkPaint& paint, + const SkMatrix& matrix) SK_OVERRIDE; + virtual void shadeSpan(int x, int y, SkPMColor span[], int count) SK_OVERRIDE; + virtual void shadeSpan16(int x, int y, uint16_t span[], int count) SK_OVERRIDE; + virtual void shadeSpanAlpha(int x, int y, uint8_t alpha[], int count) SK_OVERRIDE; // we return false for this, use asAGradient virtual BitmapType asABitmap(SkBitmap* outTexture, @@ -75,7 +56,11 @@ protected: virtual void flatten(SkWriteBuffer&) const SK_OVERRIDE; private: + SkColor fColor; // ignored if fInheritColor is true + SkPMColor fPMColor; // cached after setContext() + uint32_t fFlags; // cached after setContext() + uint16_t fColor16; // cached after setContext() SkBool8 fInheritColor; typedef SkShader INHERITED; diff --git a/include/core/SkComposeShader.h b/include/core/SkComposeShader.h index 9833a9f4ad..b54e5efa97 100644 --- a/include/core/SkComposeShader.h +++ b/include/core/SkComposeShader.h @@ -34,38 +34,10 @@ public: SkComposeShader(SkShader* sA, SkShader* sB, SkXfermode* mode = NULL); virtual ~SkComposeShader(); - virtual bool validContext(const SkBitmap&, const SkPaint&, - const SkMatrix&, SkMatrix* totalInverse = NULL) const SK_OVERRIDE; - virtual SkShader::Context* createContext(const SkBitmap&, const SkPaint&, - const SkMatrix&, void*) const SK_OVERRIDE; - virtual size_t contextSize() const SK_OVERRIDE; - - class ComposeShaderContext : public SkShader::Context { - public: - // When this object gets destroyed, it will call contextA and contextB's destructor - // but it will NOT free the memory. - ComposeShaderContext(const SkComposeShader&, const SkBitmap&, - const SkPaint&, const SkMatrix&, - SkShader::Context* contextA, SkShader::Context* contextB); - - SkShader::Context* getShaderContextA() const { return fShaderContextA; } - SkShader::Context* getShaderContextB() const { return fShaderContextB; } - - virtual ~ComposeShaderContext(); - - virtual void shadeSpan(int x, int y, SkPMColor[], int count) SK_OVERRIDE; - - private: - SkShader::Context* fShaderContextA; - SkShader::Context* fShaderContextB; - - typedef SkShader::Context INHERITED; - }; - -#if SK_DEBUG - SkShader* getShaderA() { return fShaderA; } - SkShader* getShaderB() { return fShaderB; } -#endif + virtual bool setContext(const SkBitmap&, const SkPaint&, + const SkMatrix&) SK_OVERRIDE; + virtual void endContext() SK_OVERRIDE; + virtual void shadeSpan(int x, int y, SkPMColor[], int count) SK_OVERRIDE; SK_TO_STRING_OVERRIDE() SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkComposeShader) @@ -75,6 +47,7 @@ protected: virtual void flatten(SkWriteBuffer&) const SK_OVERRIDE; private: + SkShader* fShaderA; SkShader* fShaderB; SkXfermode* fMode; diff --git a/include/core/SkEmptyShader.h b/include/core/SkEmptyShader.h index 7494eff3d0..d2ebb61221 100644 --- a/include/core/SkEmptyShader.h +++ b/include/core/SkEmptyShader.h @@ -15,28 +15,20 @@ /** * \class SkEmptyShader - * A Shader that always draws nothing. Its createContext always returns NULL. + * A Shader that always draws nothing. Its setContext always returns false, + * so it never expects that its shadeSpan() methods will get called. */ class SK_API SkEmptyShader : public SkShader { public: SkEmptyShader() {} - virtual size_t contextSize() const SK_OVERRIDE { - // Even though createContext returns NULL we have to return a value of at least - // sizeof(SkShader::Context) to satisfy SkSmallAllocator. - return sizeof(SkShader::Context); - } - - virtual bool validContext(const SkBitmap&, const SkPaint&, - const SkMatrix&, SkMatrix* totalInverse = NULL) const SK_OVERRIDE { - return false; - } - - virtual SkShader::Context* createContext(const SkBitmap&, const SkPaint&, - const SkMatrix&, void*) const SK_OVERRIDE { - // validContext returns false. - return NULL; - } + virtual uint32_t getFlags() SK_OVERRIDE; + virtual uint8_t getSpan16Alpha() const SK_OVERRIDE; + virtual bool setContext(const SkBitmap&, const SkPaint&, + const SkMatrix&) SK_OVERRIDE; + virtual void shadeSpan(int x, int y, SkPMColor span[], int count) SK_OVERRIDE; + virtual void shadeSpan16(int x, int y, uint16_t span[], int count) SK_OVERRIDE; + virtual void shadeSpanAlpha(int x, int y, uint8_t alpha[], int count) SK_OVERRIDE; SK_TO_STRING_OVERRIDE() SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkEmptyShader) diff --git a/include/core/SkShader.h b/include/core/SkShader.h index 58e5a6ad2e..076ecf5460 100644 --- a/include/core/SkShader.h +++ b/include/core/SkShader.h @@ -38,7 +38,7 @@ public: virtual ~SkShader(); /** - * Returns true if the local matrix is not an identity matrix. + * Returns true if the local matrix is not an identity matrix. */ bool hasLocalMatrix() const { return !fLocalMatrix.isIdentity(); } @@ -96,7 +96,7 @@ public: */ kIntrinsicly16_Flag = 0x04, - /** set if the spans only vary in X (const in Y). + /** set (after setContext) 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(). @@ -112,111 +112,84 @@ public: }; /** + * 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() { return 0; } + + /** * Returns true if the shader is guaranteed to produce only opaque * colors, subject to the SkPaint using the shader to apply an opaque * alpha value. Subclasses should override this to allow some - * optimizations. + * optimizations. isOpaque() can be called at any time, unlike getFlags, + * which only works properly when the context is set. */ virtual bool isOpaque() const { return false; } - class Context : public ::SkNoncopyable { - public: - Context(const SkShader& shader, const SkBitmap& device, - const SkPaint& paint, const SkMatrix& matrix); - - 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; } - - /** - * Return the alpha associated with the data returned by shadeSpan16(). If - * kHasSpan16_Flag is not set, this value is meaningless. - */ - virtual uint8_t getSpan16Alpha() const { return fPaintAlpha; } + /** + * Return the alpha associated with the data returned by shadeSpan16(). If + * kHasSpan16_Flag is not set, this value is meaningless. + */ + virtual uint8_t getSpan16Alpha() const { return fPaintAlpha; } - /** - * 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; + /** + * Called once before drawing, with the current paint and device matrix. + * Return true if your shader supports these parameters, or false if not. + * If false is returned, nothing will be drawn. If true is returned, then + * a balancing call to endContext() will be made before the next call to + * setContext. + * + * Subclasses should be sure to call their INHERITED::setContext() if they + * override this method. + */ + virtual bool setContext(const SkBitmap& device, const SkPaint& paint, + const SkMatrix& matrix); - typedef void (*ShadeProc)(void* ctx, int x, int y, SkPMColor[], int count); - virtual ShadeProc asAShadeProc(void** ctx); + /** + * Assuming setContext returned true, endContext() will be called when + * the draw using the shader has completed. It is an error for setContext + * to be called twice w/o an intervening call to endContext(). + * + * Subclasses should be sure to call their INHERITED::endContext() if they + * override this method. + */ + virtual void endContext(); - /** - * Called only for 16bit devices when getFlags() returns - * kOpaqueAlphaFlag | kHasSpan16_Flag - */ - virtual void shadeSpan16(int x, int y, uint16_t[], int count); + SkDEBUGCODE(bool setContextHasBeenCalled() const { return SkToBool(fInSetContext); }) - /** - * 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); + /** + * 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; - /** - * Helper function that returns true if this shader's shadeSpan16() method - * can be called. - */ - bool canCallShadeSpan16() { - return SkShader::CanCallShadeSpan16(this->getFlags()); - } - - 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; } - - private: - SkMatrix fTotalInverse; - uint8_t fPaintAlpha; - uint8_t fTotalInverseClass; - - typedef SkNoncopyable INHERITED; - }; + typedef void (*ShadeProc)(void* ctx, int x, int y, SkPMColor[], int count); + virtual ShadeProc asAShadeProc(void** ctx); /** - * Subclasses should be sure to call their INHERITED::validContext() if - * they override this method. + * Called only for 16bit devices when getFlags() returns + * kOpaqueAlphaFlag | kHasSpan16_Flag */ - virtual bool validContext(const SkBitmap& device, const SkPaint& paint, - const SkMatrix& matrix, SkMatrix* totalInverse = NULL) const; + virtual void shadeSpan16(int x, int y, uint16_t[], int count); /** - * Create the actual object that does the shading. - * Returns NULL if validContext() returns false. - * Size of storage must be >= contextSize. + * 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 Context* createContext(const SkBitmap& device, - const SkPaint& paint, - const SkMatrix& matrix, - void* storage) const = 0; + virtual void shadeSpanAlpha(int x, int y, uint8_t alpha[], int count); /** - * Return the size of a Context returned by createContext. + * Helper function that returns true if this shader's shadeSpan16() method + * can be called. */ - virtual size_t contextSize() const = 0; + bool canCallShadeSpan16() { + return SkShader::CanCallShadeSpan16(this->getFlags()); + } /** * Helper to check the flags to know if it is legal to call shadeSpan16() @@ -349,7 +322,7 @@ public: * The incoming color to the effect has r=g=b=a all extracted from the SkPaint's alpha. * The output color should be the computed SkShader premul color modulated by the incoming * color. The GrContext may be used by the effect to create textures. The GPU device does not - * call createContext. Instead we pass the SkPaint here in case the shader needs paint info. + * call setContext. Instead we pass the SkPaint here in case the shader needs paint info. */ virtual GrEffectRef* asNewEffect(GrContext* context, const SkPaint& paint) const; @@ -387,14 +360,26 @@ public: SK_DEFINE_FLATTENABLE_TYPE(SkShader) protected: + 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&); + + // These can be called by your subclass after setContext() has been called + uint8_t getPaintAlpha() const { return fPaintAlpha; } + const SkMatrix& getTotalInverse() const { return fTotalInverse; } + MatrixClass getInverseClass() const { return (MatrixClass)fTotalInverseClass; } SkShader(SkReadBuffer& ); virtual void flatten(SkWriteBuffer&) const SK_OVERRIDE; - private: SkMatrix fLocalMatrix; - - bool computeTotalInverse(const SkMatrix& matrix, SkMatrix* totalInverse) const; + SkMatrix fTotalInverse; + uint8_t fPaintAlpha; + uint8_t fTotalInverseClass; + SkDEBUGCODE(SkBool8 fInSetContext;) typedef SkFlattenable INHERITED; }; diff --git a/include/effects/SkPerlinNoiseShader.h b/include/effects/SkPerlinNoiseShader.h index 5b270293b1..dfd5a8c1e7 100644 --- a/include/effects/SkPerlinNoiseShader.h +++ b/include/effects/SkPerlinNoiseShader.h @@ -72,32 +72,10 @@ public: } - virtual SkShader::Context* createContext( - const SkBitmap& device, const SkPaint& paint, - const SkMatrix& matrix, void* storage) const SK_OVERRIDE; - virtual size_t contextSize() const SK_OVERRIDE; - - class PerlinNoiseShaderContext : public SkShader::Context { - public: - PerlinNoiseShaderContext(const SkPerlinNoiseShader& shader, const SkBitmap& device, - const SkPaint& paint, const SkMatrix& matrix); - virtual ~PerlinNoiseShaderContext() {} - - virtual void shadeSpan(int x, int y, SkPMColor[], int count) SK_OVERRIDE; - virtual void shadeSpan16(int x, int y, uint16_t[], int count) SK_OVERRIDE; - - private: - SkPMColor shade(const SkPoint& point, StitchData& stitchData) const; - SkScalar calculateTurbulenceValueForPoint( - int channel, const PaintingData& paintingData, - StitchData& stitchData, const SkPoint& point) const; - SkScalar noise2D(int channel, const PaintingData& paintingData, - const StitchData& stitchData, const SkPoint& noiseVector) const; - - SkMatrix fMatrix; - - typedef SkShader::Context INHERITED; - }; + virtual bool setContext(const SkBitmap& device, const SkPaint& paint, + const SkMatrix& matrix); + virtual void shadeSpan(int x, int y, SkPMColor[], int count) SK_OVERRIDE; + virtual void shadeSpan16(int x, int y, uint16_t[], int count) SK_OVERRIDE; virtual GrEffectRef* asNewEffect(GrContext* context, const SkPaint&) const SK_OVERRIDE; @@ -114,6 +92,14 @@ private: const SkISize* tileSize); virtual ~SkPerlinNoiseShader(); + SkScalar noise2D(int channel, const PaintingData& paintingData, + const StitchData& stitchData, const SkPoint& noiseVector) const; + + SkScalar calculateTurbulenceValueForPoint(int channel, const PaintingData& paintingData, + StitchData& stitchData, const SkPoint& point) const; + + SkPMColor shade(const SkPoint& point, StitchData& stitchData) const; + // TODO (scroggo): Once all SkShaders are created from a factory, and we have removed the // constructor that creates SkPerlinNoiseShader from an SkReadBuffer, several fields can // be made constant. @@ -124,6 +110,8 @@ private: /*const*/ SkScalar fSeed; /*const*/ SkISize fTileSize; /*const*/ bool fStitchTiles; + // TODO (scroggo): Once setContext creates a new object, place this on that object. + SkMatrix fMatrix; PaintingData* fPaintingData; diff --git a/include/effects/SkTransparentShader.h b/include/effects/SkTransparentShader.h index 790e5ae9fd..7428d442e3 100644 --- a/include/effects/SkTransparentShader.h +++ b/include/effects/SkTransparentShader.h @@ -14,31 +14,21 @@ class SK_API SkTransparentShader : public SkShader { public: SkTransparentShader() {} - virtual SkShader::Context* createContext(const SkBitmap& device, const SkPaint& paint, - const SkMatrix& matrix, void* storage) const - SK_OVERRIDE; - virtual size_t contextSize() const SK_OVERRIDE; - - class TransparentShaderContext : public SkShader::Context { - public: - TransparentShaderContext(const SkTransparentShader& shader, const SkBitmap& device, - const SkPaint& paint, const SkMatrix& matrix); - virtual ~TransparentShaderContext(); - - virtual uint32_t getFlags() const SK_OVERRIDE; - virtual void shadeSpan(int x, int y, SkPMColor[], int count) SK_OVERRIDE; - virtual void shadeSpan16(int x, int y, uint16_t span[], int count) SK_OVERRIDE; - - private: - const SkBitmap* fDevice; - - typedef SkShader::Context INHERITED; - }; + virtual uint32_t getFlags() SK_OVERRIDE; + virtual bool setContext(const SkBitmap& device, + const SkPaint& paint, + const SkMatrix& matrix) SK_OVERRIDE; + virtual void shadeSpan(int x, int y, SkPMColor[], int count) SK_OVERRIDE; + virtual void shadeSpan16(int x, int y, uint16_t span[], int count) SK_OVERRIDE; SK_TO_STRING_OVERRIDE() SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkTransparentShader) private: + // these are a cache from the call to setContext() + const SkBitmap* fDevice; + uint8_t fAlpha; + SkTransparentShader(SkReadBuffer& buffer) : INHERITED(buffer) {} typedef SkShader INHERITED; diff --git a/src/core/SkBitmapProcShader.cpp b/src/core/SkBitmapProcShader.cpp index 5f5eb1866e..a397b78439 100644 --- a/src/core/SkBitmapProcShader.cpp +++ b/src/core/SkBitmapProcShader.cpp @@ -34,16 +34,18 @@ bool SkBitmapProcShader::CanDo(const SkBitmap& bm, TileMode tx, TileMode ty) { SkBitmapProcShader::SkBitmapProcShader(const SkBitmap& src, TileMode tmx, TileMode tmy) { fRawBitmap = src; - fTileModeX = (uint8_t)tmx; - fTileModeY = (uint8_t)tmy; + fState.fTileModeX = (uint8_t)tmx; + fState.fTileModeY = (uint8_t)tmy; + fFlags = 0; // computed in setContext } SkBitmapProcShader::SkBitmapProcShader(SkReadBuffer& buffer) : INHERITED(buffer) { buffer.readBitmap(&fRawBitmap); fRawBitmap.setImmutable(); - fTileModeX = buffer.readUInt(); - fTileModeY = buffer.readUInt(); + fState.fTileModeX = buffer.readUInt(); + fState.fTileModeY = buffer.readUInt(); + fFlags = 0; // computed in setContext } SkShader::BitmapType SkBitmapProcShader::asABitmap(SkBitmap* texture, @@ -56,8 +58,8 @@ SkShader::BitmapType SkBitmapProcShader::asABitmap(SkBitmap* texture, texM->reset(); } if (xy) { - xy[0] = (TileMode)fTileModeX; - xy[1] = (TileMode)fTileModeY; + xy[0] = (TileMode)fState.fTileModeX; + xy[1] = (TileMode)fState.fTileModeY; } return kDefault_BitmapType; } @@ -66,8 +68,8 @@ void SkBitmapProcShader::flatten(SkWriteBuffer& buffer) const { this->INHERITED::flatten(buffer); buffer.writeBitmap(fRawBitmap); - buffer.writeUInt(fTileModeX); - buffer.writeUInt(fTileModeY); + buffer.writeUInt(fState.fTileModeX); + buffer.writeUInt(fState.fTileModeY); } static bool only_scale_and_translate(const SkMatrix& matrix) { @@ -96,67 +98,25 @@ static bool valid_for_drawing(const SkBitmap& bm) { return true; } -bool SkBitmapProcShader::validInternal(const SkBitmap& device, - const SkPaint& paint, - const SkMatrix& matrix, - SkMatrix* totalInverse, - SkBitmapProcState* state) const { +bool SkBitmapProcShader::setContext(const SkBitmap& device, + const SkPaint& paint, + const SkMatrix& matrix) { if (!fRawBitmap.getTexture() && !valid_for_drawing(fRawBitmap)) { return false; } - // Make sure we can use totalInverse as a cache. - SkMatrix totalInverseLocal; - if (NULL == totalInverse) { - totalInverse = &totalInverseLocal; - } - - // Do this first, so we know the matrix can be inverted. - if (!this->INHERITED::validContext(device, paint, matrix, totalInverse)) { + // do this first, so we have a correct inverse matrix + if (!this->INHERITED::setContext(device, paint, matrix)) { return false; } - SkASSERT(state); - state->fTileModeX = fTileModeX; - state->fTileModeY = fTileModeY; - state->fOrigBitmap = fRawBitmap; - return state->chooseProcs(*totalInverse, paint); -} - -bool SkBitmapProcShader::validContext(const SkBitmap& device, - const SkPaint& paint, - const SkMatrix& matrix, - SkMatrix* totalInverse) const { - SkBitmapProcState state; - return this->validInternal(device, paint, matrix, totalInverse, &state); -} - -SkShader::Context* SkBitmapProcShader::createContext(const SkBitmap& device, const SkPaint& paint, - const SkMatrix& matrix, void* storage) const { - void* stateStorage = (char*)storage + sizeof(BitmapProcShaderContext); - SkBitmapProcState* state = SkNEW_PLACEMENT(stateStorage, SkBitmapProcState); - if (!this->validInternal(device, paint, matrix, NULL, state)) { - state->~SkBitmapProcState(); - return NULL; + fState.fOrigBitmap = fRawBitmap; + if (!fState.chooseProcs(this->getTotalInverse(), paint)) { + this->INHERITED::endContext(); + return false; } - return SkNEW_PLACEMENT_ARGS(storage, BitmapProcShaderContext, - (*this, device, paint, matrix, state)); -} - -size_t SkBitmapProcShader::contextSize() const { - // The SkBitmapProcState is stored outside of the context object, with the context holding - // a pointer to it. - return sizeof(BitmapProcShaderContext) + sizeof(SkBitmapProcState); -} - -SkBitmapProcShader::BitmapProcShaderContext::BitmapProcShaderContext( - const SkBitmapProcShader& shader, const SkBitmap& device, - const SkPaint& paint, const SkMatrix& matrix, SkBitmapProcState* state) - : INHERITED(shader, device, paint, matrix) - , fState(state) -{ - const SkBitmap& bitmap = *fState->fBitmap; + const SkBitmap& bitmap = *fState.fBitmap; bool bitmapIsOpaque = bitmap.isOpaque(); // update fFlags @@ -197,12 +157,12 @@ SkBitmapProcShader::BitmapProcShaderContext::BitmapProcShaderContext( } fFlags = flags; + return true; } -SkBitmapProcShader::BitmapProcShaderContext::~BitmapProcShaderContext() { - // The bitmap proc state has been created outside of the context on memory that will be freed - // elsewhere. Only call the destructor but leave the freeing of the memory to the caller. - fState->~SkBitmapProcState(); +void SkBitmapProcShader::endContext() { + fState.endContext(); + this->INHERITED::endContext(); } #define BUF_MAX 128 @@ -216,9 +176,8 @@ SkBitmapProcShader::BitmapProcShaderContext::~BitmapProcShaderContext() { #define TEST_BUFFER_EXTRA 0 #endif -void SkBitmapProcShader::BitmapProcShaderContext::shadeSpan(int x, int y, SkPMColor dstC[], - int count) { - const SkBitmapProcState& state = *fState; +void SkBitmapProcShader::shadeSpan(int x, int y, SkPMColor dstC[], int count) { + const SkBitmapProcState& state = fState; if (state.getShaderProc32()) { state.getShaderProc32()(state, x, y, dstC, count); return; @@ -227,7 +186,7 @@ void SkBitmapProcShader::BitmapProcShaderContext::shadeSpan(int x, int y, SkPMCo uint32_t buffer[BUF_MAX + TEST_BUFFER_EXTRA]; SkBitmapProcState::MatrixProc mproc = state.getMatrixProc(); SkBitmapProcState::SampleProc32 sproc = state.getSampleProc32(); - int max = state.maxCountForBufferSize(sizeof(buffer[0]) * BUF_MAX); + int max = fState.maxCountForBufferSize(sizeof(buffer[0]) * BUF_MAX); SkASSERT(state.fBitmap->getPixels()); SkASSERT(state.fBitmap->pixelRef() == NULL || @@ -261,17 +220,16 @@ void SkBitmapProcShader::BitmapProcShaderContext::shadeSpan(int x, int y, SkPMCo } } -SkShader::Context::ShadeProc SkBitmapProcShader::BitmapProcShaderContext::asAShadeProc(void** ctx) { - if (fState->getShaderProc32()) { - *ctx = fState; - return (ShadeProc)fState->getShaderProc32(); +SkShader::ShadeProc SkBitmapProcShader::asAShadeProc(void** ctx) { + if (fState.getShaderProc32()) { + *ctx = &fState; + return (ShadeProc)fState.getShaderProc32(); } return NULL; } -void SkBitmapProcShader::BitmapProcShaderContext::shadeSpan16(int x, int y, uint16_t dstC[], - int count) { - const SkBitmapProcState& state = *fState; +void SkBitmapProcShader::shadeSpan16(int x, int y, uint16_t dstC[], int count) { + const SkBitmapProcState& state = fState; if (state.getShaderProc16()) { state.getShaderProc16()(state, x, y, dstC, count); return; @@ -280,7 +238,7 @@ void SkBitmapProcShader::BitmapProcShaderContext::shadeSpan16(int x, int y, uint uint32_t buffer[BUF_MAX]; SkBitmapProcState::MatrixProc mproc = state.getMatrixProc(); SkBitmapProcState::SampleProc16 sproc = state.getSampleProc16(); - int max = state.maxCountForBufferSize(sizeof(buffer)); + int max = fState.maxCountForBufferSize(sizeof(buffer)); SkASSERT(state.fBitmap->getPixels()); SkASSERT(state.fBitmap->pixelRef() == NULL || @@ -384,8 +342,8 @@ void SkBitmapProcShader::toString(SkString* str) const { str->append("BitmapShader: ("); str->appendf("(%s, %s)", - gTileModeName[fTileModeX], - gTileModeName[fTileModeY]); + gTileModeName[fState.fTileModeX], + gTileModeName[fState.fTileModeY]); str->append(" "); fRawBitmap.toString(str); @@ -426,8 +384,8 @@ GrEffectRef* SkBitmapProcShader::asNewEffect(GrContext* context, const SkPaint& matrix.preConcat(lmInverse); SkShader::TileMode tm[] = { - (TileMode)fTileModeX, - (TileMode)fTileModeY, + (TileMode)fState.fTileModeX, + (TileMode)fState.fTileModeY, }; // Must set wrap and filter on the sampler before requesting a texture. In two places below diff --git a/src/core/SkBitmapProcShader.h b/src/core/SkBitmapProcShader.h index e0c78b8e45..8e225a5e98 100644 --- a/src/core/SkBitmapProcShader.h +++ b/src/core/SkBitmapProcShader.h @@ -20,16 +20,14 @@ public: // overrides from SkShader virtual bool isOpaque() const SK_OVERRIDE; + virtual bool setContext(const SkBitmap&, const SkPaint&, const SkMatrix&) SK_OVERRIDE; + virtual void endContext() SK_OVERRIDE; + virtual uint32_t getFlags() SK_OVERRIDE { return fFlags; } + virtual void shadeSpan(int x, int y, SkPMColor dstC[], int count) SK_OVERRIDE; + virtual ShadeProc asAShadeProc(void** ctx) SK_OVERRIDE; + virtual void shadeSpan16(int x, int y, uint16_t dstC[], int count) SK_OVERRIDE; virtual BitmapType asABitmap(SkBitmap*, SkMatrix*, TileMode*) const SK_OVERRIDE; - virtual bool validContext(const SkBitmap& device, - const SkPaint& paint, - const SkMatrix& matrix, - SkMatrix* totalInverse = NULL) const SK_OVERRIDE; - virtual SkShader::Context* createContext(const SkBitmap&, const SkPaint&, - const SkMatrix&, void* storage) const SK_OVERRIDE; - virtual size_t contextSize() const SK_OVERRIDE; - static bool CanDo(const SkBitmap&, TileMode tx, TileMode ty); SK_TO_STRING_OVERRIDE() @@ -39,54 +37,22 @@ public: GrEffectRef* asNewEffect(GrContext*, const SkPaint&) const SK_OVERRIDE; #endif - class BitmapProcShaderContext : public SkShader::Context { - public: - // The context takes ownership of the state. It will call its destructor - // but will NOT free the memory. - BitmapProcShaderContext(const SkBitmapProcShader& shader, - const SkBitmap& device, - const SkPaint& paint, - const SkMatrix& matrix, - SkBitmapProcState* state); - virtual ~BitmapProcShaderContext(); - - virtual void shadeSpan(int x, int y, SkPMColor dstC[], int count) SK_OVERRIDE; - virtual ShadeProc asAShadeProc(void** ctx) SK_OVERRIDE; - virtual void shadeSpan16(int x, int y, uint16_t dstC[], int count) SK_OVERRIDE; - - virtual uint32_t getFlags() const SK_OVERRIDE { return fFlags; } - - private: - SkBitmapProcState* fState; - uint32_t fFlags; - - typedef SkShader::Context INHERITED; - }; - protected: SkBitmapProcShader(SkReadBuffer& ); virtual void flatten(SkWriteBuffer&) const SK_OVERRIDE; - SkBitmap fRawBitmap; // experimental for RLE encoding - uint8_t fTileModeX, fTileModeY; + SkBitmap fRawBitmap; // experimental for RLE encoding + SkBitmapProcState fState; + uint32_t fFlags; private: - bool validInternal(const SkBitmap& device, const SkPaint& paint, - const SkMatrix& matrix, SkMatrix* totalInverse, - SkBitmapProcState* state) const; - typedef SkShader INHERITED; }; -// Commonly used allocator. It currently is only used to allocate up to 3 objects. The total -// bytes requested is calculated using one of our large shaders, its context size plus the size of -// an Sk3DBlitter in SkDraw.cpp -// Note that some contexts may contain other contexts (e.g. for compose shaders), but we've not -// yet found a situation where the size below isn't big enough. -typedef SkSmallAllocator<3, sizeof(SkBitmapProcShader) + - sizeof(SkBitmapProcShader::BitmapProcShaderContext) + - sizeof(SkBitmapProcState) + - sizeof(void*) * 2> SkTBlitterAllocator; +// Commonly used allocator. It currently is only used to allocate up to 2 objects. The total +// bytes requested is calculated using one of our large shaders plus the size of an Sk3DBlitter +// in SkDraw.cpp +typedef SkSmallAllocator<2, sizeof(SkBitmapProcShader) + sizeof(void*) * 2> SkTBlitterAllocator; // If alloc is non-NULL, it will be used to allocate the returned SkShader, and MUST outlive // the SkShader. diff --git a/src/core/SkBitmapProcState.cpp b/src/core/SkBitmapProcState.cpp index 1936f6a23b..be87d832fd 100644 --- a/src/core/SkBitmapProcState.cpp +++ b/src/core/SkBitmapProcState.cpp @@ -399,7 +399,6 @@ bool SkBitmapProcState::chooseProcs(const SkMatrix& inv, const SkPaint& paint) { } // The above logic should have always assigned fBitmap, but in case it // didn't, we check for that now... - // TODO(dominikg): Ask humper@ if we can just use an SkASSERT(fBitmap)? if (NULL == fBitmap) { return false; } @@ -488,7 +487,6 @@ bool SkBitmapProcState::chooseProcs(const SkMatrix& inv, const SkPaint& paint) { // shader will perform. fMatrixProc = this->chooseMatrixProc(trivialMatrix); - // TODO(dominikg): SkASSERT(fMatrixProc) instead? chooseMatrixProc never returns NULL. if (NULL == fMatrixProc) { return false; } @@ -530,7 +528,6 @@ bool SkBitmapProcState::chooseProcs(const SkMatrix& inv, const SkPaint& paint) { fPaintPMColor = SkPreMultiplyColor(paint.getColor()); break; default: - // TODO(dominikg): Should we ever get here? SkASSERT(false) instead? return false; } diff --git a/src/core/SkBlitter.cpp b/src/core/SkBlitter.cpp index ad51874271..52a05eded8 100644 --- a/src/core/SkBlitter.cpp +++ b/src/core/SkBlitter.cpp @@ -26,15 +26,6 @@ SkBlitter::~SkBlitter() {} bool SkBlitter::isNullBlitter() const { return false; } -bool SkBlitter::resetShaderContext(const SkBitmap& device, const SkPaint& paint, - const SkMatrix& matrix) { - return true; -} - -SkShader::Context* SkBlitter::getShaderContext() const { - return NULL; -} - const SkBitmap* SkBlitter::justAnOpaqueColor(uint32_t* value) { return NULL; } @@ -577,149 +568,102 @@ class Sk3DShader : public SkShader { public: Sk3DShader(SkShader* proxy) : fProxy(proxy) { SkSafeRef(proxy); + fMask = NULL; } virtual ~Sk3DShader() { SkSafeUnref(fProxy); } - virtual size_t contextSize() const SK_OVERRIDE { - size_t size = sizeof(Sk3DShaderContext); - if (fProxy) { - size += fProxy->contextSize(); - } - return size; - } + void setMask(const SkMask* mask) { fMask = mask; } - virtual bool validContext(const SkBitmap& device, const SkPaint& paint, - const SkMatrix& matrix, SkMatrix* totalInverse = NULL) const - SK_OVERRIDE - { - if (!this->INHERITED::validContext(device, paint, matrix, totalInverse)) { + virtual bool setContext(const SkBitmap& device, const SkPaint& paint, + const SkMatrix& matrix) SK_OVERRIDE { + if (!this->INHERITED::setContext(device, paint, matrix)) { return false; } if (fProxy) { - return fProxy->validContext(device, paint, matrix); + if (!fProxy->setContext(device, paint, matrix)) { + // must keep our set/end context calls balanced + this->INHERITED::endContext(); + return false; + } + } else { + fPMColor = SkPreMultiplyColor(paint.getColor()); } return true; } - virtual SkShader::Context* createContext(const SkBitmap& device, - const SkPaint& paint, - const SkMatrix& matrix, - void* storage) const SK_OVERRIDE - { - if (!this->validContext(device, paint, matrix)) { - return NULL; - } - - SkShader::Context* proxyContext; + virtual void endContext() SK_OVERRIDE { if (fProxy) { - char* proxyContextStorage = (char*) storage + sizeof(Sk3DShaderContext); - proxyContext = fProxy->createContext(device, paint, matrix, proxyContextStorage); - SkASSERT(proxyContext); - } else { - proxyContext = NULL; + fProxy->endContext(); } - return SkNEW_PLACEMENT_ARGS(storage, Sk3DShaderContext, (*this, device, paint, matrix, - proxyContext)); + this->INHERITED::endContext(); } - class Sk3DShaderContext : public SkShader::Context { - public: - // Calls proxyContext's destructor but will NOT free its memory. - Sk3DShaderContext(const Sk3DShader& shader, const SkBitmap& device, const SkPaint& paint, - const SkMatrix& matrix, SkShader::Context* proxyContext) - : INHERITED(shader, device, paint, matrix) - , fMask(NULL) - , fProxyContext(proxyContext) - { - if (!fProxyContext) { - fPMColor = SkPreMultiplyColor(paint.getColor()); - } + virtual void shadeSpan(int x, int y, SkPMColor span[], int count) SK_OVERRIDE { + if (fProxy) { + fProxy->shadeSpan(x, y, span, count); } - virtual ~Sk3DShaderContext() { - if (fProxyContext) { - fProxyContext->SkShader::Context::~Context(); + if (fMask == NULL) { + if (fProxy == NULL) { + sk_memset32(span, fPMColor, count); } + return; } - void setMask(const SkMask* mask) { fMask = mask; } + SkASSERT(fMask->fBounds.contains(x, y)); + SkASSERT(fMask->fBounds.contains(x + count - 1, y)); - virtual void shadeSpan(int x, int y, SkPMColor span[], int count) SK_OVERRIDE { - if (fProxyContext) { - fProxyContext->shadeSpan(x, y, span, count); - } + size_t size = fMask->computeImageSize(); + const uint8_t* alpha = fMask->getAddr8(x, y); + const uint8_t* mulp = alpha + size; + const uint8_t* addp = mulp + size; - if (fMask == NULL) { - if (fProxyContext == NULL) { - sk_memset32(span, fPMColor, count); - } - return; - } + if (fProxy) { + for (int i = 0; i < count; i++) { + if (alpha[i]) { + SkPMColor c = span[i]; + if (c) { + unsigned a = SkGetPackedA32(c); + unsigned r = SkGetPackedR32(c); + unsigned g = SkGetPackedG32(c); + unsigned b = SkGetPackedB32(c); - SkASSERT(fMask->fBounds.contains(x, y)); - SkASSERT(fMask->fBounds.contains(x + count - 1, y)); - - size_t size = fMask->computeImageSize(); - const uint8_t* alpha = fMask->getAddr8(x, y); - const uint8_t* mulp = alpha + size; - const uint8_t* addp = mulp + size; - - if (fProxyContext) { - for (int i = 0; i < count; i++) { - if (alpha[i]) { - SkPMColor c = span[i]; - if (c) { - unsigned a = SkGetPackedA32(c); - unsigned r = SkGetPackedR32(c); - unsigned g = SkGetPackedG32(c); - unsigned b = SkGetPackedB32(c); - - unsigned mul = SkAlpha255To256(mulp[i]); - unsigned add = addp[i]; - - r = SkFastMin32(SkAlphaMul(r, mul) + add, a); - g = SkFastMin32(SkAlphaMul(g, mul) + add, a); - b = SkFastMin32(SkAlphaMul(b, mul) + add, a); - - span[i] = SkPackARGB32(a, r, g, b); - } - } else { - span[i] = 0; - } - } - } else { // color - unsigned a = SkGetPackedA32(fPMColor); - unsigned r = SkGetPackedR32(fPMColor); - unsigned g = SkGetPackedG32(fPMColor); - unsigned b = SkGetPackedB32(fPMColor); - for (int i = 0; i < count; i++) { - if (alpha[i]) { unsigned mul = SkAlpha255To256(mulp[i]); unsigned add = addp[i]; - span[i] = SkPackARGB32( a, - SkFastMin32(SkAlphaMul(r, mul) + add, a), - SkFastMin32(SkAlphaMul(g, mul) + add, a), - SkFastMin32(SkAlphaMul(b, mul) + add, a)); - } else { - span[i] = 0; + r = SkFastMin32(SkAlphaMul(r, mul) + add, a); + g = SkFastMin32(SkAlphaMul(g, mul) + add, a); + b = SkFastMin32(SkAlphaMul(b, mul) + add, a); + + span[i] = SkPackARGB32(a, r, g, b); } + } else { + span[i] = 0; + } + } + } else { // color + unsigned a = SkGetPackedA32(fPMColor); + unsigned r = SkGetPackedR32(fPMColor); + unsigned g = SkGetPackedG32(fPMColor); + unsigned b = SkGetPackedB32(fPMColor); + for (int i = 0; i < count; i++) { + if (alpha[i]) { + unsigned mul = SkAlpha255To256(mulp[i]); + unsigned add = addp[i]; + + span[i] = SkPackARGB32( a, + SkFastMin32(SkAlphaMul(r, mul) + add, a), + SkFastMin32(SkAlphaMul(g, mul) + add, a), + SkFastMin32(SkAlphaMul(b, mul) + add, a)); + } else { + span[i] = 0; } } } - - private: - // Unowned. - const SkMask* fMask; - // Memory is unowned, but we need to call the destructor. - SkShader::Context* fProxyContext; - SkPMColor fPMColor; - - typedef SkShader::Context INHERITED; - }; + } #ifndef SK_IGNORE_TO_STRING virtual void toString(SkString* str) const SK_OVERRIDE { @@ -741,30 +685,29 @@ public: protected: Sk3DShader(SkReadBuffer& buffer) : INHERITED(buffer) { fProxy = buffer.readShader(); - // Leaving this here until we bump the picture version, though this - // shader should never be recorded. - buffer.readColor(); + fPMColor = buffer.readColor(); + fMask = NULL; } virtual void flatten(SkWriteBuffer& buffer) const SK_OVERRIDE { this->INHERITED::flatten(buffer); buffer.writeFlattenable(fProxy); - // Leaving this here until we bump the picture version, though this - // shader should never be recorded. - buffer.writeColor(SkColor()); + buffer.writeColor(fPMColor); } private: SkShader* fProxy; + SkPMColor fPMColor; + const SkMask* fMask; typedef SkShader INHERITED; }; class Sk3DBlitter : public SkBlitter { public: - Sk3DBlitter(SkBlitter* proxy, Sk3DShader::Sk3DShaderContext* shaderContext) + Sk3DBlitter(SkBlitter* proxy, Sk3DShader* shader) : fProxy(proxy) - , f3DShaderContext(shaderContext) + , f3DShader(SkRef(shader)) {} virtual void blitH(int x, int y, int width) { @@ -786,22 +729,22 @@ public: virtual void blitMask(const SkMask& mask, const SkIRect& clip) { if (mask.fFormat == SkMask::k3D_Format) { - f3DShaderContext->setMask(&mask); + f3DShader->setMask(&mask); ((SkMask*)&mask)->fFormat = SkMask::kA8_Format; fProxy->blitMask(mask, clip); ((SkMask*)&mask)->fFormat = SkMask::k3D_Format; - f3DShaderContext->setMask(NULL); + f3DShader->setMask(NULL); } else { fProxy->blitMask(mask, clip); } } private: - // Both pointers are unowned. They will be deleted by SkSmallAllocator. - SkBlitter* fProxy; - Sk3DShader::Sk3DShaderContext* f3DShaderContext; + // fProxy is unowned. It will be deleted by SkSmallAllocator. + SkBlitter* fProxy; + SkAutoTUnref<Sk3DShader> f3DShader; }; /////////////////////////////////////////////////////////////////////////////// @@ -811,7 +754,8 @@ private: static bool just_solid_color(const SkPaint& paint) { if (paint.getAlpha() == 0xFF && paint.getColorFilter() == NULL) { SkShader* shader = paint.getShader(); - if (NULL == shader) { + if (NULL == shader || + (shader->getFlags() & SkShader::kOpaqueAlpha_Flag)) { return true; } } @@ -949,22 +893,16 @@ SkBlitter* SkBlitter::Choose(const SkBitmap& device, } /* - * We create a SkShader::Context object, and store it on the blitter. + * We need to have balanced calls to the shader: + * setContext + * endContext + * We make the first call here, in case it fails we can abort the draw. + * The endContext() call is made by the blitter (assuming setContext did + * not fail) in its destructor. */ - SkShader::Context* shaderContext; - if (shader) { - // Try to create the ShaderContext - void* storage = allocator->reserveT<SkShader::Context>(shader->contextSize()); - shaderContext = shader->createContext(device, *paint, matrix, storage); - if (!shaderContext) { - allocator->freeLast(); - blitter = allocator->createT<SkNullBlitter>(); - return blitter; - } - SkASSERT(shaderContext); - SkASSERT((void*) shaderContext == storage); - } else { - shaderContext = NULL; + if (shader && !shader->setContext(device, *paint, matrix)) { + blitter = allocator->createT<SkNullBlitter>(); + return blitter; } @@ -975,20 +913,19 @@ SkBlitter* SkBlitter::Choose(const SkBitmap& device, SkASSERT(NULL == paint->getXfermode()); blitter = allocator->createT<SkA8_Coverage_Blitter>(device, *paint); } else if (shader) { - blitter = allocator->createT<SkA8_Shader_Blitter>(device, *paint, shaderContext); + blitter = allocator->createT<SkA8_Shader_Blitter>(device, *paint); } else { blitter = allocator->createT<SkA8_Blitter>(device, *paint); } break; case kRGB_565_SkColorType: - blitter = SkBlitter_ChooseD565(device, *paint, shaderContext, allocator); + blitter = SkBlitter_ChooseD565(device, *paint, allocator); break; case kN32_SkColorType: if (shader) { - blitter = allocator->createT<SkARGB32_Shader_Blitter>( - device, *paint, shaderContext); + blitter = allocator->createT<SkARGB32_Shader_Blitter>(device, *paint); } else if (paint->getColor() == SK_ColorBLACK) { blitter = allocator->createT<SkARGB32_Black_Blitter>(device, *paint); } else if (paint->getAlpha() == 0xFF) { @@ -1007,9 +944,7 @@ SkBlitter* SkBlitter::Choose(const SkBitmap& device, if (shader3D) { SkBlitter* innerBlitter = blitter; // innerBlitter was allocated by allocator, which will delete it. - // We know shaderContext is of type Sk3DShaderContext because it belongs to shader3D. - blitter = allocator->createT<Sk3DBlitter>(innerBlitter, - static_cast<Sk3DShader::Sk3DShaderContext*>(shaderContext)); + blitter = allocator->createT<Sk3DBlitter>(innerBlitter, shader3D); } return blitter; } @@ -1021,36 +956,18 @@ const uint32_t gMask_00FF00FF = 0xFF00FF; /////////////////////////////////////////////////////////////////////////////// -SkShaderBlitter::SkShaderBlitter(const SkBitmap& device, const SkPaint& paint, - SkShader::Context* shaderContext) - : INHERITED(device) - , fShader(paint.getShader()) - , fShaderContext(shaderContext) { +SkShaderBlitter::SkShaderBlitter(const SkBitmap& device, const SkPaint& paint) + : INHERITED(device) { + fShader = paint.getShader(); SkASSERT(fShader); - SkASSERT(fShaderContext); + SkASSERT(fShader->setContextHasBeenCalled()); fShader->ref(); - fShaderFlags = fShaderContext->getFlags(); + fShaderFlags = fShader->getFlags(); } SkShaderBlitter::~SkShaderBlitter() { + SkASSERT(fShader->setContextHasBeenCalled()); + fShader->endContext(); fShader->unref(); } - -bool SkShaderBlitter::resetShaderContext(const SkBitmap& device, const SkPaint& paint, - const SkMatrix& matrix) { - if (!fShader->validContext(device, paint, matrix)) { - return false; - } - - // Only destroy the old context if we have a new one. We need to ensure to have a - // live context in fShaderContext because the storage is owned by an SkSmallAllocator - // outside of this class. - // The new context will be of the same size as the old one because we use the same - // shader to create it. It is therefore safe to re-use the storage. - fShaderContext->SkShader::Context::~Context(); - fShaderContext = fShader->createContext(device, paint, matrix, (void*)fShaderContext); - SkASSERT(fShaderContext); - - return true; -} diff --git a/src/core/SkBlitter.h b/src/core/SkBlitter.h index f76839e8b6..d19a34badc 100644 --- a/src/core/SkBlitter.h +++ b/src/core/SkBlitter.h @@ -61,13 +61,6 @@ public: */ virtual bool isNullBlitter() const; - /** - * Special methods for SkShaderBlitter. On all other classes this is a no-op. - */ - virtual bool resetShaderContext(const SkBitmap& device, const SkPaint& paint, - const SkMatrix& matrix); - virtual SkShader::Context* getShaderContext() const; - ///@name non-virtual helpers void blitMaskRegion(const SkMask& mask, const SkRegion& clip); void blitRectRegion(const SkIRect& rect, const SkRegion& clip); diff --git a/src/core/SkBlitter_A8.cpp b/src/core/SkBlitter_A8.cpp index 11f425903b..983a226e34 100644 --- a/src/core/SkBlitter_A8.cpp +++ b/src/core/SkBlitter_A8.cpp @@ -228,12 +228,11 @@ void SkA8_Blitter::blitRect(int x, int y, int width, int height) { /////////////////////////////////////////////////////////////////////// -SkA8_Shader_Blitter::SkA8_Shader_Blitter(const SkBitmap& device, const SkPaint& paint, - SkShader::Context* shaderContext) - : INHERITED(device, paint, shaderContext) { +SkA8_Shader_Blitter::SkA8_Shader_Blitter(const SkBitmap& device, const SkPaint& paint) + : INHERITED(device, paint) { if ((fXfermode = paint.getXfermode()) != NULL) { fXfermode->ref(); - SkASSERT(fShaderContext); + SkASSERT(fShader); } int width = device.width(); @@ -251,14 +250,13 @@ void SkA8_Shader_Blitter::blitH(int x, int y, int width) { (unsigned)(x + width) <= (unsigned)fDevice.width()); uint8_t* device = fDevice.getAddr8(x, y); - SkShader::Context* shaderContext = fShaderContext; - if ((shaderContext->getFlags() & SkShader::kOpaqueAlpha_Flag) && !fXfermode) { + if ((fShader->getFlags() & SkShader::kOpaqueAlpha_Flag) && !fXfermode) { memset(device, 0xFF, width); } else { SkPMColor* span = fBuffer; - shaderContext->shadeSpan(x, y, span, width); + fShader->shadeSpan(x, y, span, width); if (fXfermode) { fXfermode->xferA8(device, span, width, NULL); } else { @@ -284,12 +282,12 @@ static inline uint8_t aa_blend8(SkPMColor src, U8CPU da, int aa) { void SkA8_Shader_Blitter::blitAntiH(int x, int y, const SkAlpha antialias[], const int16_t runs[]) { - SkShader::Context* shaderContext = fShaderContext; - SkXfermode* mode = fXfermode; - uint8_t* aaExpand = fAAExpand; - SkPMColor* span = fBuffer; - uint8_t* device = fDevice.getAddr8(x, y); - int opaque = shaderContext->getFlags() & SkShader::kOpaqueAlpha_Flag; + SkShader* shader = fShader; + SkXfermode* mode = fXfermode; + uint8_t* aaExpand = fAAExpand; + SkPMColor* span = fBuffer; + uint8_t* device = fDevice.getAddr8(x, y); + int opaque = fShader->getFlags() & SkShader::kOpaqueAlpha_Flag; for (;;) { int count = *runs; @@ -301,7 +299,7 @@ void SkA8_Shader_Blitter::blitAntiH(int x, int y, const SkAlpha antialias[], if (opaque && aa == 255 && mode == NULL) { memset(device, 0xFF, count); } else { - shaderContext->shadeSpan(x, y, span, count); + shader->shadeSpan(x, y, span, count); if (mode) { memset(aaExpand, aa, count); mode->xferA8(device, span, count, aaExpand); @@ -331,12 +329,11 @@ void SkA8_Shader_Blitter::blitMask(const SkMask& mask, const SkIRect& clip) { int height = clip.height(); uint8_t* device = fDevice.getAddr8(x, y); const uint8_t* alpha = mask.getAddr8(x, y); - SkShader::Context* shaderContext = fShaderContext; SkPMColor* span = fBuffer; while (--height >= 0) { - shaderContext->shadeSpan(x, y, span, width); + fShader->shadeSpan(x, y, span, width); if (fXfermode) { fXfermode->xferA8(device, span, width, alpha); } else { diff --git a/src/core/SkBlitter_ARGB32.cpp b/src/core/SkBlitter_ARGB32.cpp index 118a1d12f3..d4bec1bc08 100644 --- a/src/core/SkBlitter_ARGB32.cpp +++ b/src/core/SkBlitter_ARGB32.cpp @@ -275,16 +275,14 @@ static void blend_srcmode(SkPMColor* SK_RESTRICT device, } SkARGB32_Shader_Blitter::SkARGB32_Shader_Blitter(const SkBitmap& device, - const SkPaint& paint, SkShader::Context* shaderContext) - : INHERITED(device, paint, shaderContext) -{ + const SkPaint& paint) : INHERITED(device, paint) { fBuffer = (SkPMColor*)sk_malloc_throw(device.width() * (sizeof(SkPMColor))); fXfermode = paint.getXfermode(); SkSafeRef(fXfermode); int flags = 0; - if (!(shaderContext->getFlags() & SkShader::kOpaqueAlpha_Flag)) { + if (!(fShader->getFlags() & SkShader::kOpaqueAlpha_Flag)) { flags |= SkBlitRow::kSrcPixelAlpha_Flag32; } // we call this on the output from the shader @@ -294,7 +292,7 @@ SkARGB32_Shader_Blitter::SkARGB32_Shader_Blitter(const SkBitmap& device, fShadeDirectlyIntoDevice = false; if (fXfermode == NULL) { - if (shaderContext->getFlags() & SkShader::kOpaqueAlpha_Flag) { + if (fShader->getFlags() & SkShader::kOpaqueAlpha_Flag) { fShadeDirectlyIntoDevice = true; } } else { @@ -307,7 +305,7 @@ SkARGB32_Shader_Blitter::SkARGB32_Shader_Blitter(const SkBitmap& device, } } - fConstInY = SkToBool(shaderContext->getFlags() & SkShader::kConstInY32_Flag); + fConstInY = SkToBool(fShader->getFlags() & SkShader::kConstInY32_Flag); } SkARGB32_Shader_Blitter::~SkARGB32_Shader_Blitter() { @@ -321,10 +319,10 @@ void SkARGB32_Shader_Blitter::blitH(int x, int y, int width) { uint32_t* device = fDevice.getAddr32(x, y); if (fShadeDirectlyIntoDevice) { - fShaderContext->shadeSpan(x, y, device, width); + fShader->shadeSpan(x, y, device, width); } else { SkPMColor* span = fBuffer; - fShaderContext->shadeSpan(x, y, span, width); + fShader->shadeSpan(x, y, span, width); if (fXfermode) { fXfermode->xfer32(device, span, width, NULL); } else { @@ -337,22 +335,22 @@ void SkARGB32_Shader_Blitter::blitRect(int x, int y, int width, int height) { SkASSERT(x >= 0 && y >= 0 && x + width <= fDevice.width() && y + height <= fDevice.height()); - uint32_t* device = fDevice.getAddr32(x, y); - size_t deviceRB = fDevice.rowBytes(); - SkShader::Context* shaderContext = fShaderContext; - SkPMColor* span = fBuffer; + uint32_t* device = fDevice.getAddr32(x, y); + size_t deviceRB = fDevice.rowBytes(); + SkShader* shader = fShader; + SkPMColor* span = fBuffer; if (fConstInY) { if (fShadeDirectlyIntoDevice) { // shade the first row directly into the device - shaderContext->shadeSpan(x, y, device, width); + fShader->shadeSpan(x, y, device, width); span = device; while (--height > 0) { device = (uint32_t*)((char*)device + deviceRB); memcpy(device, span, width << 2); } } else { - shaderContext->shadeSpan(x, y, span, width); + fShader->shadeSpan(x, y, span, width); SkXfermode* xfer = fXfermode; if (xfer) { do { @@ -374,7 +372,7 @@ void SkARGB32_Shader_Blitter::blitRect(int x, int y, int width, int height) { if (fShadeDirectlyIntoDevice) { void* ctx; - SkShader::Context::ShadeProc shadeProc = shaderContext->asAShadeProc(&ctx); + SkShader::ShadeProc shadeProc = fShader->asAShadeProc(&ctx); if (shadeProc) { do { shadeProc(ctx, x, y, device, width); @@ -383,7 +381,7 @@ void SkARGB32_Shader_Blitter::blitRect(int x, int y, int width, int height) { } while (--height > 0); } else { do { - shaderContext->shadeSpan(x, y, device, width); + shader->shadeSpan(x, y, device, width); y += 1; device = (uint32_t*)((char*)device + deviceRB); } while (--height > 0); @@ -392,7 +390,7 @@ void SkARGB32_Shader_Blitter::blitRect(int x, int y, int width, int height) { SkXfermode* xfer = fXfermode; if (xfer) { do { - shaderContext->shadeSpan(x, y, span, width); + shader->shadeSpan(x, y, span, width); xfer->xfer32(device, span, width, NULL); y += 1; device = (uint32_t*)((char*)device + deviceRB); @@ -400,7 +398,7 @@ void SkARGB32_Shader_Blitter::blitRect(int x, int y, int width, int height) { } else { SkBlitRow::Proc32 proc = fProc32; do { - shaderContext->shadeSpan(x, y, span, width); + shader->shadeSpan(x, y, span, width); proc(device, span, width, 255); y += 1; device = (uint32_t*)((char*)device + deviceRB); @@ -411,9 +409,9 @@ void SkARGB32_Shader_Blitter::blitRect(int x, int y, int width, int height) { void SkARGB32_Shader_Blitter::blitAntiH(int x, int y, const SkAlpha antialias[], const int16_t runs[]) { - SkPMColor* span = fBuffer; - uint32_t* device = fDevice.getAddr32(x, y); - SkShader::Context* shaderContext = fShaderContext; + SkPMColor* span = fBuffer; + uint32_t* device = fDevice.getAddr32(x, y); + SkShader* shader = fShader; if (fXfermode && !fShadeDirectlyIntoDevice) { for (;;) { @@ -424,7 +422,7 @@ void SkARGB32_Shader_Blitter::blitAntiH(int x, int y, const SkAlpha antialias[], break; int aa = *antialias; if (aa) { - shaderContext->shadeSpan(x, y, span, count); + shader->shadeSpan(x, y, span, count); if (aa == 255) { xfer->xfer32(device, span, count, NULL); } else { @@ -440,7 +438,7 @@ void SkARGB32_Shader_Blitter::blitAntiH(int x, int y, const SkAlpha antialias[], x += count; } } else if (fShadeDirectlyIntoDevice || - (shaderContext->getFlags() & SkShader::kOpaqueAlpha_Flag)) { + (fShader->getFlags() & SkShader::kOpaqueAlpha_Flag)) { for (;;) { int count = *runs; if (count <= 0) { @@ -450,9 +448,9 @@ void SkARGB32_Shader_Blitter::blitAntiH(int x, int y, const SkAlpha antialias[], if (aa) { if (aa == 255) { // cool, have the shader draw right into the device - shaderContext->shadeSpan(x, y, device, count); + shader->shadeSpan(x, y, device, count); } else { - shaderContext->shadeSpan(x, y, span, count); + shader->shadeSpan(x, y, span, count); fProc32Blend(device, span, count, aa); } } @@ -469,7 +467,7 @@ void SkARGB32_Shader_Blitter::blitAntiH(int x, int y, const SkAlpha antialias[], } int aa = *antialias; if (aa) { - shaderContext->shadeSpan(x, y, span, count); + fShader->shadeSpan(x, y, span, count); if (aa == 255) { fProc32(device, span, count, 255); } else { @@ -493,11 +491,10 @@ void SkARGB32_Shader_Blitter::blitMask(const SkMask& mask, const SkIRect& clip) SkASSERT(mask.fBounds.contains(clip)); - SkShader::Context* shaderContext = fShaderContext; SkBlitMask::RowProc proc = NULL; if (!fXfermode) { unsigned flags = 0; - if (shaderContext->getFlags() & SkShader::kOpaqueAlpha_Flag) { + if (fShader->getFlags() & SkShader::kOpaqueAlpha_Flag) { flags |= SkBlitMask::kSrcIsOpaque_RowFlag; } proc = SkBlitMask::RowFactory(SkBitmap::kARGB_8888_Config, mask.fFormat, @@ -518,13 +515,14 @@ void SkARGB32_Shader_Blitter::blitMask(const SkMask& mask, const SkIRect& clip) const uint8_t* maskRow = (const uint8_t*)mask.getAddr(x, y); const size_t maskRB = mask.fRowBytes; + SkShader* shader = fShader; SkPMColor* span = fBuffer; if (fXfermode) { SkASSERT(SkMask::kA8_Format == mask.fFormat); SkXfermode* xfer = fXfermode; do { - shaderContext->shadeSpan(x, y, span, width); + shader->shadeSpan(x, y, span, width); xfer->xfer32((SkPMColor*)dstRow, span, width, maskRow); dstRow += dstRB; maskRow += maskRB; @@ -532,7 +530,7 @@ void SkARGB32_Shader_Blitter::blitMask(const SkMask& mask, const SkIRect& clip) } while (--height > 0); } else { do { - shaderContext->shadeSpan(x, y, span, width); + shader->shadeSpan(x, y, span, width); proc(dstRow, maskRow, span, width); dstRow += dstRB; maskRow += maskRB; @@ -544,13 +542,13 @@ void SkARGB32_Shader_Blitter::blitMask(const SkMask& mask, const SkIRect& clip) void SkARGB32_Shader_Blitter::blitV(int x, int y, int height, SkAlpha alpha) { SkASSERT(x >= 0 && y >= 0 && y + height <= fDevice.height()); - uint32_t* device = fDevice.getAddr32(x, y); - size_t deviceRB = fDevice.rowBytes(); - SkShader::Context* shaderContext = fShaderContext; + uint32_t* device = fDevice.getAddr32(x, y); + size_t deviceRB = fDevice.rowBytes(); + SkShader* shader = fShader; if (fConstInY) { SkPMColor c; - shaderContext->shadeSpan(x, y, &c, 1); + fShader->shadeSpan(x, y, &c, 1); if (fShadeDirectlyIntoDevice) { if (255 == alpha) { @@ -584,7 +582,7 @@ void SkARGB32_Shader_Blitter::blitV(int x, int y, int height, SkAlpha alpha) { if (fShadeDirectlyIntoDevice) { void* ctx; - SkShader::Context::ShadeProc shadeProc = shaderContext->asAShadeProc(&ctx); + SkShader::ShadeProc shadeProc = fShader->asAShadeProc(&ctx); if (255 == alpha) { if (shadeProc) { do { @@ -594,7 +592,7 @@ void SkARGB32_Shader_Blitter::blitV(int x, int y, int height, SkAlpha alpha) { } while (--height > 0); } else { do { - shaderContext->shadeSpan(x, y, device, 1); + shader->shadeSpan(x, y, device, 1); y += 1; device = (uint32_t*)((char*)device + deviceRB); } while (--height > 0); @@ -610,7 +608,7 @@ void SkARGB32_Shader_Blitter::blitV(int x, int y, int height, SkAlpha alpha) { } while (--height > 0); } else { do { - shaderContext->shadeSpan(x, y, &c, 1); + shader->shadeSpan(x, y, &c, 1); *device = SkFourByteInterp(c, *device, alpha); y += 1; device = (uint32_t*)((char*)device + deviceRB); @@ -622,7 +620,7 @@ void SkARGB32_Shader_Blitter::blitV(int x, int y, int height, SkAlpha alpha) { SkXfermode* xfer = fXfermode; if (xfer) { do { - shaderContext->shadeSpan(x, y, span, 1); + shader->shadeSpan(x, y, span, 1); xfer->xfer32(device, span, 1, &alpha); y += 1; device = (uint32_t*)((char*)device + deviceRB); @@ -630,7 +628,7 @@ void SkARGB32_Shader_Blitter::blitV(int x, int y, int height, SkAlpha alpha) { } else { SkBlitRow::Proc32 proc = (255 == alpha) ? fProc32 : fProc32Blend; do { - shaderContext->shadeSpan(x, y, span, 1); + shader->shadeSpan(x, y, span, 1); proc(device, span, 1, alpha); y += 1; device = (uint32_t*)((char*)device + deviceRB); diff --git a/src/core/SkBlitter_RGB16.cpp b/src/core/SkBlitter_RGB16.cpp index e22aac4eda..21b5a16e3c 100644 --- a/src/core/SkBlitter_RGB16.cpp +++ b/src/core/SkBlitter_RGB16.cpp @@ -107,8 +107,7 @@ private: class SkRGB16_Shader_Blitter : public SkShaderBlitter { public: - SkRGB16_Shader_Blitter(const SkBitmap& device, const SkPaint& paint, - SkShader::Context* shaderContext); + SkRGB16_Shader_Blitter(const SkBitmap& device, const SkPaint& paint); virtual ~SkRGB16_Shader_Blitter(); virtual void blitH(int x, int y, int width); virtual void blitAntiH(int x, int y, const SkAlpha* antialias, @@ -130,8 +129,7 @@ private: // used only if the shader can perform shadSpan16 class SkRGB16_Shader16_Blitter : public SkRGB16_Shader_Blitter { public: - SkRGB16_Shader16_Blitter(const SkBitmap& device, const SkPaint& paint, - SkShader::Context* shaderContext); + SkRGB16_Shader16_Blitter(const SkBitmap& device, const SkPaint& paint); virtual void blitH(int x, int y, int width); virtual void blitAntiH(int x, int y, const SkAlpha* antialias, const int16_t* runs); @@ -143,8 +141,7 @@ private: class SkRGB16_Shader_Xfermode_Blitter : public SkShaderBlitter { public: - SkRGB16_Shader_Xfermode_Blitter(const SkBitmap& device, const SkPaint& paint, - SkShader::Context* shaderContext); + SkRGB16_Shader_Xfermode_Blitter(const SkBitmap& device, const SkPaint& paint); virtual ~SkRGB16_Shader_Xfermode_Blitter(); virtual void blitH(int x, int y, int width); virtual void blitAntiH(int x, int y, const SkAlpha* antialias, @@ -682,9 +679,8 @@ void SkRGB16_Blitter::blitRect(int x, int y, int width, int height) { /////////////////////////////////////////////////////////////////////////////// SkRGB16_Shader16_Blitter::SkRGB16_Shader16_Blitter(const SkBitmap& device, - const SkPaint& paint, - SkShader::Context* shaderContext) - : SkRGB16_Shader_Blitter(device, paint, shaderContext) { + const SkPaint& paint) + : SkRGB16_Shader_Blitter(device, paint) { SkASSERT(SkShader::CanCallShadeSpan16(fShaderFlags)); } @@ -692,28 +688,28 @@ void SkRGB16_Shader16_Blitter::blitH(int x, int y, int width) { SkASSERT(x + width <= fDevice.width()); uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y); - SkShader::Context* shaderContext = fShaderContext; + SkShader* shader = fShader; - int alpha = shaderContext->getSpan16Alpha(); + int alpha = shader->getSpan16Alpha(); if (0xFF == alpha) { - shaderContext->shadeSpan16(x, y, device, width); + shader->shadeSpan16(x, y, device, width); } else { uint16_t* span16 = (uint16_t*)fBuffer; - shaderContext->shadeSpan16(x, y, span16, width); + shader->shadeSpan16(x, y, span16, width); SkBlendRGB16(span16, device, SkAlpha255To256(alpha), width); } } void SkRGB16_Shader16_Blitter::blitRect(int x, int y, int width, int height) { - SkShader::Context* shaderContext = fShaderContext; - uint16_t* dst = fDevice.getAddr16(x, y); - size_t dstRB = fDevice.rowBytes(); - int alpha = shaderContext->getSpan16Alpha(); + SkShader* shader = fShader; + uint16_t* dst = fDevice.getAddr16(x, y); + size_t dstRB = fDevice.rowBytes(); + int alpha = shader->getSpan16Alpha(); if (0xFF == alpha) { if (fShaderFlags & SkShader::kConstInY16_Flag) { // have the shader blit directly into the device the first time - shaderContext->shadeSpan16(x, y, dst, width); + shader->shadeSpan16(x, y, dst, width); // and now just memcpy that line on the subsequent lines if (--height > 0) { const uint16_t* orig = dst; @@ -724,7 +720,7 @@ void SkRGB16_Shader16_Blitter::blitRect(int x, int y, int width, int height) { } } else { // need to call shadeSpan16 for every line do { - shaderContext->shadeSpan16(x, y, dst, width); + shader->shadeSpan16(x, y, dst, width); y += 1; dst = (uint16_t*)((char*)dst + dstRB); } while (--height); @@ -733,14 +729,14 @@ void SkRGB16_Shader16_Blitter::blitRect(int x, int y, int width, int height) { int scale = SkAlpha255To256(alpha); uint16_t* span16 = (uint16_t*)fBuffer; if (fShaderFlags & SkShader::kConstInY16_Flag) { - shaderContext->shadeSpan16(x, y, span16, width); + shader->shadeSpan16(x, y, span16, width); do { SkBlendRGB16(span16, dst, scale, width); dst = (uint16_t*)((char*)dst + dstRB); } while (--height); } else { do { - shaderContext->shadeSpan16(x, y, span16, width); + shader->shadeSpan16(x, y, span16, width); SkBlendRGB16(span16, dst, scale, width); y += 1; dst = (uint16_t*)((char*)dst + dstRB); @@ -752,11 +748,11 @@ void SkRGB16_Shader16_Blitter::blitRect(int x, int y, int width, int height) { void SkRGB16_Shader16_Blitter::blitAntiH(int x, int y, const SkAlpha* SK_RESTRICT antialias, const int16_t* SK_RESTRICT runs) { - SkShader::Context* shaderContext = fShaderContext; + SkShader* shader = fShader; SkPMColor* SK_RESTRICT span = fBuffer; - uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y); + uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y); - int alpha = shaderContext->getSpan16Alpha(); + int alpha = shader->getSpan16Alpha(); uint16_t* span16 = (uint16_t*)span; if (0xFF == alpha) { @@ -770,9 +766,9 @@ void SkRGB16_Shader16_Blitter::blitAntiH(int x, int y, int aa = *antialias; if (aa == 255) { // go direct to the device! - shaderContext->shadeSpan16(x, y, device, count); + shader->shadeSpan16(x, y, device, count); } else if (aa) { - shaderContext->shadeSpan16(x, y, span16, count); + shader->shadeSpan16(x, y, span16, count); SkBlendRGB16(span16, device, SkAlpha255To256(aa), count); } device += count; @@ -791,7 +787,7 @@ void SkRGB16_Shader16_Blitter::blitAntiH(int x, int y, int aa = SkAlphaMul(*antialias, alpha); if (aa) { - shaderContext->shadeSpan16(x, y, span16, count); + shader->shadeSpan16(x, y, span16, count); SkBlendRGB16(span16, device, SkAlpha255To256(aa), count); } @@ -806,9 +802,8 @@ void SkRGB16_Shader16_Blitter::blitAntiH(int x, int y, /////////////////////////////////////////////////////////////////////////////// SkRGB16_Shader_Blitter::SkRGB16_Shader_Blitter(const SkBitmap& device, - const SkPaint& paint, - SkShader::Context* shaderContext) -: INHERITED(device, paint, shaderContext) { + const SkPaint& paint) +: INHERITED(device, paint) { SkASSERT(paint.getXfermode() == NULL); fBuffer = (SkPMColor*)sk_malloc_throw(device.width() * sizeof(SkPMColor)); @@ -839,20 +834,20 @@ SkRGB16_Shader_Blitter::~SkRGB16_Shader_Blitter() { void SkRGB16_Shader_Blitter::blitH(int x, int y, int width) { SkASSERT(x + width <= fDevice.width()); - fShaderContext->shadeSpan(x, y, fBuffer, width); + fShader->shadeSpan(x, y, fBuffer, width); // shaders take care of global alpha, so we pass 0xFF (should be ignored) fOpaqueProc(fDevice.getAddr16(x, y), fBuffer, width, 0xFF, x, y); } void SkRGB16_Shader_Blitter::blitRect(int x, int y, int width, int height) { - SkShader::Context* shaderContext = fShaderContext; - SkBlitRow::Proc proc = fOpaqueProc; - SkPMColor* buffer = fBuffer; - uint16_t* dst = fDevice.getAddr16(x, y); - size_t dstRB = fDevice.rowBytes(); + SkShader* shader = fShader; + SkBlitRow::Proc proc = fOpaqueProc; + SkPMColor* buffer = fBuffer; + uint16_t* dst = fDevice.getAddr16(x, y); + size_t dstRB = fDevice.rowBytes(); if (fShaderFlags & SkShader::kConstInY32_Flag) { - shaderContext->shadeSpan(x, y, buffer, width); + shader->shadeSpan(x, y, buffer, width); do { proc(dst, buffer, width, 0xFF, x, y); y += 1; @@ -860,7 +855,7 @@ void SkRGB16_Shader_Blitter::blitRect(int x, int y, int width, int height) { } while (--height); } else { do { - shaderContext->shadeSpan(x, y, buffer, width); + shader->shadeSpan(x, y, buffer, width); proc(dst, buffer, width, 0xFF, x, y); y += 1; dst = (uint16_t*)((char*)dst + dstRB); @@ -885,9 +880,9 @@ static inline int count_nonzero_span(const int16_t runs[], const SkAlpha aa[]) { void SkRGB16_Shader_Blitter::blitAntiH(int x, int y, const SkAlpha* SK_RESTRICT antialias, const int16_t* SK_RESTRICT runs) { - SkShader::Context* shaderContext = fShaderContext; + SkShader* shader = fShader; SkPMColor* SK_RESTRICT span = fBuffer; - uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y); + uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y); for (;;) { int count = *runs; @@ -906,7 +901,7 @@ void SkRGB16_Shader_Blitter::blitAntiH(int x, int y, int nonZeroCount = count + count_nonzero_span(runs + count, antialias + count); SkASSERT(nonZeroCount <= fDevice.width()); // don't overrun fBuffer - shaderContext->shadeSpan(x, y, span, nonZeroCount); + shader->shadeSpan(x, y, span, nonZeroCount); SkPMColor* localSpan = span; for (;;) { @@ -933,9 +928,8 @@ void SkRGB16_Shader_Blitter::blitAntiH(int x, int y, /////////////////////////////////////////////////////////////////////// SkRGB16_Shader_Xfermode_Blitter::SkRGB16_Shader_Xfermode_Blitter( - const SkBitmap& device, const SkPaint& paint, - SkShader::Context* shaderContext) -: INHERITED(device, paint, shaderContext) { + const SkBitmap& device, const SkPaint& paint) +: INHERITED(device, paint) { fXfermode = paint.getXfermode(); SkASSERT(fXfermode); fXfermode->ref(); @@ -956,18 +950,18 @@ void SkRGB16_Shader_Xfermode_Blitter::blitH(int x, int y, int width) { uint16_t* device = fDevice.getAddr16(x, y); SkPMColor* span = fBuffer; - fShaderContext->shadeSpan(x, y, span, width); + fShader->shadeSpan(x, y, span, width); fXfermode->xfer16(device, span, width, NULL); } void SkRGB16_Shader_Xfermode_Blitter::blitAntiH(int x, int y, const SkAlpha* SK_RESTRICT antialias, const int16_t* SK_RESTRICT runs) { - SkShader::Context* shaderContext = fShaderContext; - SkXfermode* mode = fXfermode; + SkShader* shader = fShader; + SkXfermode* mode = fXfermode; SkPMColor* SK_RESTRICT span = fBuffer; - uint8_t* SK_RESTRICT aaExpand = fAAExpand; - uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y); + uint8_t* SK_RESTRICT aaExpand = fAAExpand; + uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y); for (;;) { int count = *runs; @@ -987,7 +981,7 @@ void SkRGB16_Shader_Xfermode_Blitter::blitAntiH(int x, int y, antialias + count); SkASSERT(nonZeroCount <= fDevice.width()); // don't overrun fBuffer - shaderContext->shadeSpan(x, y, span, nonZeroCount); + shader->shadeSpan(x, y, span, nonZeroCount); x += nonZeroCount; SkPMColor* localSpan = span; @@ -1018,7 +1012,6 @@ void SkRGB16_Shader_Xfermode_Blitter::blitAntiH(int x, int y, /////////////////////////////////////////////////////////////////////////////// SkBlitter* SkBlitter_ChooseD565(const SkBitmap& device, const SkPaint& paint, - SkShader::Context* shaderContext, SkTBlitterAllocator* allocator) { SkASSERT(allocator != NULL); @@ -1030,14 +1023,12 @@ SkBlitter* SkBlitter_ChooseD565(const SkBitmap& device, const SkPaint& paint, SkASSERT(NULL == mode || NULL != shader); if (shader) { - SkASSERT(shaderContext != NULL); if (mode) { - blitter = allocator->createT<SkRGB16_Shader_Xfermode_Blitter>(device, paint, - shaderContext); - } else if (shaderContext->canCallShadeSpan16()) { - blitter = allocator->createT<SkRGB16_Shader16_Blitter>(device, paint, shaderContext); + blitter = allocator->createT<SkRGB16_Shader_Xfermode_Blitter>(device, paint); + } else if (shader->canCallShadeSpan16()) { + blitter = allocator->createT<SkRGB16_Shader16_Blitter>(device, paint); } else { - blitter = allocator->createT<SkRGB16_Shader_Blitter>(device, paint, shaderContext); + blitter = allocator->createT<SkRGB16_Shader_Blitter>(device, paint); } } else { // no shader, no xfermode, (and we always ignore colorfilter) diff --git a/src/core/SkCanvas.cpp b/src/core/SkCanvas.cpp index c1d2726d8c..569e9e59ba 100644 --- a/src/core/SkCanvas.cpp +++ b/src/core/SkCanvas.cpp @@ -91,10 +91,32 @@ private: }; #endif +class AutoCheckNoSetContext { +public: + AutoCheckNoSetContext(const SkPaint& paint) : fPaint(paint) { + this->assertNoSetContext(fPaint); + } + ~AutoCheckNoSetContext() { + this->assertNoSetContext(fPaint); + } + +private: + const SkPaint& fPaint; + + void assertNoSetContext(const SkPaint& paint) { + SkShader* s = paint.getShader(); + if (s) { + SkASSERT(!s->setContextHasBeenCalled()); + } + } +}; + #define CHECK_LOCKCOUNT_BALANCE(bitmap) AutoCheckLockCountBalance clcb(bitmap) +#define CHECK_SHADER_NOSETCONTEXT(paint) AutoCheckNoSetContext cshsc(paint) #else #define CHECK_LOCKCOUNT_BALANCE(bitmap) + #define CHECK_SHADER_NOSETCONTEXT(paint) #endif typedef SkTLazy<SkPaint> SkLazyPaint; @@ -1913,6 +1935,8 @@ void SkCanvas::drawPaint(const SkPaint& paint) { } void SkCanvas::internalDrawPaint(const SkPaint& paint) { + CHECK_SHADER_NOSETCONTEXT(paint); + LOOPER_BEGIN(paint, SkDrawFilter::kPaint_Type, NULL) while (iter.next()) { @@ -1928,6 +1952,8 @@ void SkCanvas::drawPoints(PointMode mode, size_t count, const SkPoint pts[], return; } + CHECK_SHADER_NOSETCONTEXT(paint); + SkRect r, storage; const SkRect* bounds = NULL; if (paint.canComputeFastBounds()) { @@ -1955,6 +1981,8 @@ void SkCanvas::drawPoints(PointMode mode, size_t count, const SkPoint pts[], } void SkCanvas::drawRect(const SkRect& r, const SkPaint& paint) { + CHECK_SHADER_NOSETCONTEXT(paint); + SkRect storage; const SkRect* bounds = NULL; if (paint.canComputeFastBounds()) { @@ -1974,6 +2002,8 @@ void SkCanvas::drawRect(const SkRect& r, const SkPaint& paint) { } void SkCanvas::drawOval(const SkRect& oval, const SkPaint& paint) { + CHECK_SHADER_NOSETCONTEXT(paint); + SkRect storage; const SkRect* bounds = NULL; if (paint.canComputeFastBounds()) { @@ -1993,6 +2023,8 @@ void SkCanvas::drawOval(const SkRect& oval, const SkPaint& paint) { } void SkCanvas::drawRRect(const SkRRect& rrect, const SkPaint& paint) { + CHECK_SHADER_NOSETCONTEXT(paint); + SkRect storage; const SkRect* bounds = NULL; if (paint.canComputeFastBounds()) { @@ -2023,6 +2055,8 @@ void SkCanvas::drawRRect(const SkRRect& rrect, const SkPaint& paint) { void SkCanvas::onDrawDRRect(const SkRRect& outer, const SkRRect& inner, const SkPaint& paint) { + CHECK_SHADER_NOSETCONTEXT(paint); + SkRect storage; const SkRect* bounds = NULL; if (paint.canComputeFastBounds()) { @@ -2042,6 +2076,8 @@ void SkCanvas::onDrawDRRect(const SkRRect& outer, const SkRRect& inner, } void SkCanvas::drawPath(const SkPath& path, const SkPaint& paint) { + CHECK_SHADER_NOSETCONTEXT(paint); + if (!path.isFinite()) { return; } @@ -2317,6 +2353,8 @@ void SkCanvas::DrawTextDecorations(const SkDraw& draw, const SkPaint& paint, void SkCanvas::drawText(const void* text, size_t byteLength, SkScalar x, SkScalar y, const SkPaint& paint) { + CHECK_SHADER_NOSETCONTEXT(paint); + LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, NULL) while (iter.next()) { @@ -2331,6 +2369,8 @@ void SkCanvas::drawText(const void* text, size_t byteLength, void SkCanvas::drawPosText(const void* text, size_t byteLength, const SkPoint pos[], const SkPaint& paint) { + CHECK_SHADER_NOSETCONTEXT(paint); + LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, NULL) while (iter.next()) { @@ -2345,6 +2385,8 @@ void SkCanvas::drawPosText(const void* text, size_t byteLength, void SkCanvas::drawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[], SkScalar constY, const SkPaint& paint) { + CHECK_SHADER_NOSETCONTEXT(paint); + LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, NULL) while (iter.next()) { @@ -2359,6 +2401,8 @@ void SkCanvas::drawPosTextH(const void* text, size_t byteLength, void SkCanvas::drawTextOnPath(const void* text, size_t byteLength, const SkPath& path, const SkMatrix* matrix, const SkPaint& paint) { + CHECK_SHADER_NOSETCONTEXT(paint); + LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, NULL) while (iter.next()) { @@ -2374,6 +2418,8 @@ void SkCanvas::drawVertices(VertexMode vmode, int vertexCount, const SkColor colors[], SkXfermode* xmode, const uint16_t indices[], int indexCount, const SkPaint& paint) { + CHECK_SHADER_NOSETCONTEXT(paint); + LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type, NULL) while (iter.next()) { diff --git a/src/core/SkComposeShader.cpp b/src/core/SkComposeShader.cpp index 68c4646cf6..f53eedf876 100644 --- a/src/core/SkComposeShader.cpp +++ b/src/core/SkComposeShader.cpp @@ -45,10 +45,6 @@ SkComposeShader::~SkComposeShader() { fShaderA->unref(); } -size_t SkComposeShader::contextSize() const { - return sizeof(ComposeShaderContext) + fShaderA->contextSize() + fShaderB->contextSize(); -} - class SkAutoAlphaRestore { public: SkAutoAlphaRestore(SkPaint* paint, uint8_t newAlpha) { @@ -73,16 +69,17 @@ void SkComposeShader::flatten(SkWriteBuffer& buffer) const { buffer.writeFlattenable(fMode); } -/* We call validContext/createContext on our two worker shaders. - However, we always let them see opaque alpha, and if the paint - really is translucent, then we apply that after the fact. +/* We call setContext on our two worker shaders. However, we + always let them see opaque alpha, and if the paint really + is translucent, then we apply that after the fact. + We need to keep the calls to setContext/endContext balanced, since if we + return false, our endContext() will not be called. */ -bool SkComposeShader::validContext(const SkBitmap& device, - const SkPaint& paint, - const SkMatrix& matrix, - SkMatrix* totalInverse) const { - if (!this->INHERITED::validContext(device, paint, matrix, totalInverse)) { +bool SkComposeShader::setContext(const SkBitmap& device, + const SkPaint& paint, + const SkMatrix& matrix) { + if (!this->INHERITED::setContext(device, paint, matrix)) { return false; } @@ -93,62 +90,38 @@ bool SkComposeShader::validContext(const SkBitmap& device, tmpM.setConcat(matrix, this->getLocalMatrix()); - return fShaderA->validContext(device, paint, tmpM) && - fShaderB->validContext(device, paint, tmpM); -} - -SkShader::Context* SkComposeShader::createContext(const SkBitmap& device, const SkPaint& paint, - const SkMatrix& matrix, void* storage) const { - if (!this->validContext(device, paint, matrix)) { - return NULL; - } - - // we preconcat our localMatrix (if any) with the device matrix - // before calling our sub-shaders - - SkMatrix tmpM; - - tmpM.setConcat(matrix, this->getLocalMatrix()); - SkAutoAlphaRestore restore(const_cast<SkPaint*>(&paint), 0xFF); - char* aStorage = (char*) storage + sizeof(ComposeShaderContext); - char* bStorage = aStorage + fShaderA->contextSize(); - - SkShader::Context* contextA = fShaderA->createContext(device, paint, tmpM, aStorage); - SkShader::Context* contextB = fShaderB->createContext(device, paint, tmpM, bStorage); - - // Both functions must succeed; otherwise validContext should have returned - // false. - SkASSERT(contextA); - SkASSERT(contextB); - - return SkNEW_PLACEMENT_ARGS(storage, ComposeShaderContext, - (*this, device, paint, matrix, contextA, contextB)); + bool setContextA = fShaderA->setContext(device, paint, tmpM); + bool setContextB = fShaderB->setContext(device, paint, tmpM); + if (!setContextA || !setContextB) { + if (setContextB) { + fShaderB->endContext(); + } + else if (setContextA) { + fShaderA->endContext(); + } + this->INHERITED::endContext(); + return false; + } + return true; } -SkComposeShader::ComposeShaderContext::ComposeShaderContext( - const SkComposeShader& shader, const SkBitmap& device, - const SkPaint& paint, const SkMatrix& matrix, - SkShader::Context* contextA, SkShader::Context* contextB) - : INHERITED(shader, device, paint, matrix) - , fShaderContextA(contextA) - , fShaderContextB(contextB) {} - -SkComposeShader::ComposeShaderContext::~ComposeShaderContext() { - fShaderContextA->SkShader::Context::~Context(); - fShaderContextB->SkShader::Context::~Context(); +void SkComposeShader::endContext() { + fShaderB->endContext(); + fShaderA->endContext(); + this->INHERITED::endContext(); } // larger is better (fewer times we have to loop), but we shouldn't // take up too much stack-space (each element is 4 bytes) #define TMP_COLOR_COUNT 64 -void SkComposeShader::ComposeShaderContext::shadeSpan(int x, int y, SkPMColor result[], int count) { - SkShader::Context* shaderContextA = fShaderContextA; - SkShader::Context* shaderContextB = fShaderContextB; - SkXfermode* mode = static_cast<const SkComposeShader&>(fShader).fMode; - unsigned scale = SkAlpha255To256(this->getPaintAlpha()); +void SkComposeShader::shadeSpan(int x, int y, SkPMColor result[], int count) { + SkShader* shaderA = fShaderA; + SkShader* shaderB = fShaderB; + SkXfermode* mode = fMode; + unsigned scale = SkAlpha255To256(this->getPaintAlpha()); SkPMColor tmp[TMP_COLOR_COUNT]; @@ -161,8 +134,8 @@ void SkComposeShader::ComposeShaderContext::shadeSpan(int x, int y, SkPMColor re n = TMP_COLOR_COUNT; } - shaderContextA->shadeSpan(x, y, result, n); - shaderContextB->shadeSpan(x, y, tmp, n); + shaderA->shadeSpan(x, y, result, n); + shaderB->shadeSpan(x, y, tmp, n); if (256 == scale) { for (int i = 0; i < n; i++) { @@ -186,8 +159,8 @@ void SkComposeShader::ComposeShaderContext::shadeSpan(int x, int y, SkPMColor re n = TMP_COLOR_COUNT; } - shaderContextA->shadeSpan(x, y, result, n); - shaderContextB->shadeSpan(x, y, tmp, n); + shaderA->shadeSpan(x, y, result, n); + shaderB->shadeSpan(x, y, tmp, n); mode->xfer32(result, tmp, n, NULL); if (256 == scale) { diff --git a/src/core/SkCoreBlitters.h b/src/core/SkCoreBlitters.h index 2d22d38e78..285184050b 100644 --- a/src/core/SkCoreBlitters.h +++ b/src/core/SkCoreBlitters.h @@ -27,29 +27,12 @@ private: class SkShaderBlitter : public SkRasterBlitter { public: - /** - * The storage for shaderContext is owned by the caller, but the object itself is not. - * The blitter only ensures that the storage always holds a live object, but it may - * exchange that object. - */ - SkShaderBlitter(const SkBitmap& device, const SkPaint& paint, - SkShader::Context* shaderContext); + SkShaderBlitter(const SkBitmap& device, const SkPaint& paint); virtual ~SkShaderBlitter(); - /** - * Create a new shader context and uses it instead of the old one if successful. - * Will create the context at the same location as the old one (this is safe - * because the shader itself is unchanged). - */ - virtual bool resetShaderContext(const SkBitmap& device, const SkPaint& paint, - const SkMatrix& matrix) SK_OVERRIDE; - - virtual SkShader::Context* getShaderContext() const SK_OVERRIDE { return fShaderContext; } - protected: - uint32_t fShaderFlags; - const SkShader* fShader; - SkShader::Context* fShaderContext; + uint32_t fShaderFlags; + SkShader* fShader; private: // illegal @@ -92,8 +75,7 @@ private: class SkA8_Shader_Blitter : public SkShaderBlitter { public: - SkA8_Shader_Blitter(const SkBitmap& device, const SkPaint& paint, - SkShader::Context* shaderContext); + SkA8_Shader_Blitter(const SkBitmap& device, const SkPaint& paint); virtual ~SkA8_Shader_Blitter(); virtual void blitH(int x, int y, int width); virtual void blitAntiH(int x, int y, const SkAlpha antialias[], const int16_t runs[]); @@ -159,8 +141,7 @@ private: class SkARGB32_Shader_Blitter : public SkShaderBlitter { public: - SkARGB32_Shader_Blitter(const SkBitmap& device, const SkPaint& paint, - SkShader::Context* shaderContext); + SkARGB32_Shader_Blitter(const SkBitmap& device, const SkPaint& paint); virtual ~SkARGB32_Shader_Blitter(); virtual void blitH(int x, int y, int width) SK_OVERRIDE; virtual void blitV(int x, int y, int height, SkAlpha alpha) SK_OVERRIDE; @@ -198,7 +179,6 @@ private: */ SkBlitter* SkBlitter_ChooseD565(const SkBitmap& device, const SkPaint& paint, - SkShader::Context* shaderContext, SkTBlitterAllocator* allocator); #endif diff --git a/src/core/SkDraw.cpp b/src/core/SkDraw.cpp index 6ddd0d274f..7eb0be6b6b 100644 --- a/src/core/SkDraw.cpp +++ b/src/core/SkDraw.cpp @@ -2354,26 +2354,9 @@ class SkTriColorShader : public SkShader { public: SkTriColorShader() {} - virtual SkShader::Context* createContext( - const SkBitmap&, const SkPaint&, const SkMatrix&, void*) const SK_OVERRIDE; - virtual size_t contextSize() const SK_OVERRIDE; + bool setup(const SkPoint pts[], const SkColor colors[], int, int, int); - class TriColorShaderContext : public SkShader::Context { - public: - TriColorShaderContext(const SkTriColorShader& shader, const SkBitmap& device, - const SkPaint& paint, const SkMatrix& matrix); - virtual ~TriColorShaderContext(); - - bool setup(const SkPoint pts[], const SkColor colors[], int, int, int); - - virtual void shadeSpan(int x, int y, SkPMColor dstC[], int count) SK_OVERRIDE; - - private: - SkMatrix fDstToUnit; - SkPMColor fColors[3]; - - typedef SkShader::Context INHERITED; - }; + virtual void shadeSpan(int x, int y, SkPMColor dstC[], int count) SK_OVERRIDE; SK_TO_STRING_OVERRIDE() SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkTriColorShader) @@ -2382,20 +2365,14 @@ protected: SkTriColorShader(SkReadBuffer& buffer) : SkShader(buffer) {} private: + SkMatrix fDstToUnit; + SkPMColor fColors[3]; + typedef SkShader INHERITED; }; -SkShader::Context* SkTriColorShader::createContext(const SkBitmap& device, const SkPaint& paint, - const SkMatrix& matrix, void* storage) const { - if (!this->validContext(device, paint, matrix)) { - return NULL; - } - - return SkNEW_PLACEMENT_ARGS(storage, TriColorShaderContext, (*this, device, paint, matrix)); -} - -bool SkTriColorShader::TriColorShaderContext::setup(const SkPoint pts[], const SkColor colors[], - int index0, int index1, int index2) { +bool SkTriColorShader::setup(const SkPoint pts[], const SkColor colors[], + int index0, int index1, int index2) { fColors[0] = SkPreMultiplyColor(colors[index0]); fColors[1] = SkPreMultiplyColor(colors[index1]); @@ -2430,18 +2407,7 @@ static int ScalarTo256(SkScalar v) { return SkAlpha255To256(scale); } - -SkTriColorShader::TriColorShaderContext::TriColorShaderContext( - const SkTriColorShader& shader, const SkBitmap& device, - const SkPaint& paint, const SkMatrix& matrix) - : INHERITED(shader, device, paint, matrix) {} - -SkTriColorShader::TriColorShaderContext::~TriColorShaderContext() {} - -size_t SkTriColorShader::contextSize() const { - return sizeof(TriColorShaderContext); -} -void SkTriColorShader::TriColorShaderContext::shadeSpan(int x, int y, SkPMColor dstC[], int count) { +void SkTriColorShader::shadeSpan(int x, int y, SkPMColor dstC[], int count) { SkPoint src; for (int i = 0; i < count; i++) { @@ -2526,7 +2492,6 @@ void SkDraw::drawVertices(SkCanvas::VertexMode vmode, int count, } // setup the custom shader (if needed) - SkAutoTUnref<SkComposeShader> composeShader; if (NULL != colors) { if (NULL == textures) { // just colors (no texture) @@ -2539,8 +2504,9 @@ void SkDraw::drawVertices(SkCanvas::VertexMode vmode, int count, xmode = SkXfermode::Create(SkXfermode::kModulate_Mode); releaseMode = true; } - composeShader.reset(SkNEW_ARGS(SkComposeShader, (&triShader, shader, xmode))); - p.setShader(composeShader); + SkShader* compose = SkNEW_ARGS(SkComposeShader, + (&triShader, shader, xmode)); + p.setShader(compose)->unref(); if (releaseMode) { xmode->unref(); } @@ -2548,7 +2514,9 @@ void SkDraw::drawVertices(SkCanvas::VertexMode vmode, int count, } SkAutoBlitterChoose blitter(*fBitmap, *fMatrix, p); - // Abort early if we failed to create a shader context. + // important that we abort early, as below we may manipulate the shader + // and that is only valid if the shader returned true from setContext. + // If it returned false, then our blitter will be the NullBlitter. if (blitter->isNullBlitter()) { return; } @@ -2564,38 +2532,30 @@ void SkDraw::drawVertices(SkCanvas::VertexMode vmode, int count, savedLocalM = shader->getLocalMatrix(); } + // setContext has already been called and verified to return true + // by the constructor of SkAutoBlitterChoose + bool prevContextSuccess = true; while (vertProc(&state)) { if (NULL != textures) { if (texture_to_matrix(state, vertices, textures, &tempM)) { tempM.postConcat(savedLocalM); shader->setLocalMatrix(tempM); - if (!blitter->resetShaderContext(*fBitmap, p, *fMatrix)) { + // Need to recall setContext since we changed the local matrix. + // However, we also need to balance the calls this with a + // call to endContext which requires tracking the result of + // the previous call to setContext. + if (prevContextSuccess) { + shader->endContext(); + } + prevContextSuccess = shader->setContext(*fBitmap, p, *fMatrix); + if (!prevContextSuccess) { continue; } } } if (NULL != colors) { - // Find the context for triShader. - SkTriColorShader::TriColorShaderContext* triColorShaderContext; - - SkShader::Context* shaderContext = blitter->getShaderContext(); - SkASSERT(shaderContext); - if (p.getShader() == &triShader) { - triColorShaderContext = - static_cast<SkTriColorShader::TriColorShaderContext*>(shaderContext); - } else { - // The shader is a compose shader and triShader is its first shader. - SkASSERT(p.getShader() == composeShader); - SkASSERT(composeShader->getShaderA() == &triShader); - SkComposeShader::ComposeShaderContext* composeShaderContext = - static_cast<SkComposeShader::ComposeShaderContext*>(shaderContext); - SkShader::Context* shaderContextA = composeShaderContext->getShaderContextA(); - triColorShaderContext = - static_cast<SkTriColorShader::TriColorShaderContext*>(shaderContextA); - } - - if (!triColorShaderContext->setup(vertices, colors, - state.f0, state.f1, state.f2)) { + if (!triShader.setup(vertices, colors, + state.f0, state.f1, state.f2)) { continue; } } @@ -2610,6 +2570,13 @@ void SkDraw::drawVertices(SkCanvas::VertexMode vmode, int count, if (NULL != shader) { shader->setLocalMatrix(savedLocalM); } + + // If the final call to setContext fails we must make it suceed so that the + // call to endContext in the destructor for SkAutoBlitterChoose is balanced. + if (!prevContextSuccess) { + prevContextSuccess = shader->setContext(*fBitmap, paint, SkMatrix::I()); + SkASSERT(prevContextSuccess); + } } else { // no colors[] and no texture HairProc hairProc = ChooseHairProc(paint.isAntiAlias()); diff --git a/src/core/SkFilterShader.cpp b/src/core/SkFilterShader.cpp index 1a0255157d..58961913c8 100644 --- a/src/core/SkFilterShader.cpp +++ b/src/core/SkFilterShader.cpp @@ -38,11 +38,9 @@ void SkFilterShader::flatten(SkWriteBuffer& buffer) const { buffer.writeFlattenable(fFilter); } -uint32_t SkFilterShader::FilterShaderContext::getFlags() const { - const SkFilterShader& filterShader = static_cast<const SkFilterShader&>(fShader); - - uint32_t shaderF = fShaderContext->getFlags(); - uint32_t filterF = filterShader.fFilter->getFlags(); +uint32_t SkFilterShader::getFlags() { + uint32_t shaderF = fShader->getFlags(); + uint32_t filterF = fFilter->getFlags(); // if the filter doesn't support 16bit, clear the matching bit in the shader if (!(filterF & SkColorFilter::kHasFilter16_Flag)) { @@ -55,62 +53,38 @@ uint32_t SkFilterShader::FilterShaderContext::getFlags() const { return shaderF; } -SkShader::Context* SkFilterShader::createContext(const SkBitmap& device, - const SkPaint& paint, - const SkMatrix& matrix, - void* storage) const { - if (!this->validContext(device, paint, matrix)) { - return NULL; - } - - char* shaderContextStorage = (char*)storage + sizeof(FilterShaderContext); - SkShader::Context* shaderContext = fShader->createContext(device, paint, matrix, - shaderContextStorage); - SkASSERT(shaderContext); - - return SkNEW_PLACEMENT_ARGS(storage, FilterShaderContext, - (*this, shaderContext, device, paint, matrix)); -} - -size_t SkFilterShader::contextSize() const { - return sizeof(FilterShaderContext) + fShader->contextSize(); -} +bool SkFilterShader::setContext(const SkBitmap& device, + const SkPaint& paint, + const SkMatrix& matrix) { + // we need to keep the setContext/endContext calls balanced. If we return + // false, our endContext() will not be called. -bool SkFilterShader::validContext(const SkBitmap& device, - const SkPaint& paint, - const SkMatrix& matrix, - SkMatrix* totalInverse) const { - return this->INHERITED::validContext(device, paint, matrix, totalInverse) && - fShader->validContext(device, paint, matrix); + if (!this->INHERITED::setContext(device, paint, matrix)) { + return false; + } + if (!fShader->setContext(device, paint, matrix)) { + this->INHERITED::endContext(); + return false; + } + return true; } -SkFilterShader::FilterShaderContext::FilterShaderContext(const SkFilterShader& filterShader, - SkShader::Context* shaderContext, - const SkBitmap& device, - const SkPaint& paint, - const SkMatrix& matrix) - : INHERITED(filterShader, device, paint, matrix) - , fShaderContext(shaderContext) {} - -SkFilterShader::FilterShaderContext::~FilterShaderContext() { - fShaderContext->SkShader::Context::~Context(); +void SkFilterShader::endContext() { + fShader->endContext(); + this->INHERITED::endContext(); } -void SkFilterShader::FilterShaderContext::shadeSpan(int x, int y, SkPMColor result[], int count) { - const SkFilterShader& filterShader = static_cast<const SkFilterShader&>(fShader); - - fShaderContext->shadeSpan(x, y, result, count); - filterShader.fFilter->filterSpan(result, count, result); +void SkFilterShader::shadeSpan(int x, int y, SkPMColor result[], int count) { + fShader->shadeSpan(x, y, result, count); + fFilter->filterSpan(result, count, result); } -void SkFilterShader::FilterShaderContext::shadeSpan16(int x, int y, uint16_t result[], int count) { - const SkFilterShader& filterShader = static_cast<const SkFilterShader&>(fShader); - - SkASSERT(fShaderContext->getFlags() & SkShader::kHasSpan16_Flag); - SkASSERT(filterShader.fFilter->getFlags() & SkColorFilter::kHasFilter16_Flag); +void SkFilterShader::shadeSpan16(int x, int y, uint16_t result[], int count) { + SkASSERT(fShader->getFlags() & SkShader::kHasSpan16_Flag); + SkASSERT(fFilter->getFlags() & SkColorFilter::kHasFilter16_Flag); - fShaderContext->shadeSpan16(x, y, result, count); - filterShader.fFilter->filterSpan16(result, count, result); + fShader->shadeSpan16(x, y, result, count); + fFilter->filterSpan16(result, count, result); } #ifndef SK_IGNORE_TO_STRING diff --git a/src/core/SkFilterShader.h b/src/core/SkFilterShader.h index 4ef4577248..11add0cf17 100644 --- a/src/core/SkFilterShader.h +++ b/src/core/SkFilterShader.h @@ -17,29 +17,12 @@ public: SkFilterShader(SkShader* shader, SkColorFilter* filter); virtual ~SkFilterShader(); - virtual bool validContext(const SkBitmap&, const SkPaint&, - const SkMatrix&, SkMatrix* totalInverse = NULL) const SK_OVERRIDE; - virtual SkShader::Context* createContext(const SkBitmap&, const SkPaint&, - const SkMatrix&, void* storage) const SK_OVERRIDE; - virtual size_t contextSize() const SK_OVERRIDE; - - class FilterShaderContext : public SkShader::Context { - public: - // Takes ownership of shaderContext and calls its destructor. - FilterShaderContext(const SkFilterShader& filterShader, SkShader::Context* shaderContext, - const SkBitmap& device, const SkPaint& paint, const SkMatrix& matrix); - virtual ~FilterShaderContext(); - - virtual uint32_t getFlags() const SK_OVERRIDE; - - virtual void shadeSpan(int x, int y, SkPMColor[], int count) SK_OVERRIDE; - virtual void shadeSpan16(int x, int y, uint16_t[], int count) SK_OVERRIDE; - - private: - SkShader::Context* fShaderContext; - - typedef SkShader::Context INHERITED; - }; + virtual uint32_t getFlags() SK_OVERRIDE; + virtual bool setContext(const SkBitmap&, const SkPaint&, + const SkMatrix&) SK_OVERRIDE; + virtual void endContext() SK_OVERRIDE; + virtual void shadeSpan(int x, int y, SkPMColor[], int count) SK_OVERRIDE; + virtual void shadeSpan16(int x, int y, uint16_t[], int count) SK_OVERRIDE; SK_TO_STRING_OVERRIDE() SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkFilterShader) diff --git a/src/core/SkPictureShader.cpp b/src/core/SkPictureShader.cpp index 1e9507190c..15df3a37a5 100644 --- a/src/core/SkPictureShader.cpp +++ b/src/core/SkPictureShader.cpp @@ -55,9 +55,9 @@ void SkPictureShader::flatten(SkWriteBuffer& buffer) const { } } -SkShader* SkPictureShader::buildBitmapShader(const SkMatrix& matrix) const { +bool SkPictureShader::buildBitmapShader(const SkMatrix& matrix) const { if (!fPicture || (0 == fPicture->width() && 0 == fPicture->height())) { - return NULL; + return false; } SkMatrix m; @@ -78,20 +78,17 @@ SkShader* SkPictureShader::buildBitmapShader(const SkMatrix& matrix) const { SkISize tileSize = scaledSize.toRound(); if (tileSize.isEmpty()) { - return NULL; + return false; } // The actual scale, compensating for rounding. SkSize tileScale = SkSize::Make(SkIntToScalar(tileSize.width()) / fPicture->width(), SkIntToScalar(tileSize.height()) / fPicture->height()); - SkAutoMutexAcquire ama(fCachedBitmapShaderMutex); - - if (!fCachedBitmapShader || tileScale != fCachedTileScale || - this->getLocalMatrix() != fCachedLocalMatrix) { + if (!fCachedShader || tileScale != fCachedTileScale) { SkBitmap bm; if (!bm.allocN32Pixels(tileSize.width(), tileSize.height())) { - return NULL; + return false; } bm.eraseColor(SK_ColorTRANSPARENT); @@ -99,96 +96,66 @@ SkShader* SkPictureShader::buildBitmapShader(const SkMatrix& matrix) const { canvas.scale(tileScale.width(), tileScale.height()); canvas.drawPicture(*fPicture); - fCachedBitmapShader.reset(CreateBitmapShader(bm, fTmx, fTmy)); + fCachedShader.reset(CreateBitmapShader(bm, fTmx, fTmy)); fCachedTileScale = tileScale; - fCachedLocalMatrix = this->getLocalMatrix(); - - SkMatrix shaderMatrix = this->getLocalMatrix(); - shaderMatrix.preScale(1 / tileScale.width(), 1 / tileScale.height()); - fCachedBitmapShader->setLocalMatrix(shaderMatrix); } - // Increment the ref counter inside the mutex to ensure the returned pointer is still valid. - // Otherwise, the pointer may have been overwritten on a different thread before the object's - // ref count was incremented. - fCachedBitmapShader.get()->ref(); - return fCachedBitmapShader; -} + SkMatrix shaderMatrix = this->getLocalMatrix(); + shaderMatrix.preScale(1 / tileScale.width(), 1 / tileScale.height()); + fCachedShader->setLocalMatrix(shaderMatrix); -SkShader* SkPictureShader::validInternal(const SkBitmap& device, const SkPaint& paint, - const SkMatrix& matrix, SkMatrix* totalInverse) const { - if (!this->INHERITED::validContext(device, paint, matrix, totalInverse)) { - return NULL; - } + return true; +} - SkShader* bitmapShader = this->buildBitmapShader(matrix); - if (!bitmapShader) { - return NULL; +bool SkPictureShader::setContext(const SkBitmap& device, + const SkPaint& paint, + const SkMatrix& matrix) { + if (!this->buildBitmapShader(matrix)) { + return false; } - if (!bitmapShader->validContext(device, paint, matrix)) { - bitmapShader->unref(); - return NULL; + if (!this->INHERITED::setContext(device, paint, matrix)) { + return false; } - return bitmapShader; -} - -bool SkPictureShader::validContext(const SkBitmap& device, const SkPaint& paint, - const SkMatrix& matrix, SkMatrix* totalInverse) const { - SkAutoTUnref<SkShader> shader(this->validInternal(device, paint, matrix, totalInverse)); - return shader != NULL; -} - -SkShader::Context* SkPictureShader::createContext(const SkBitmap& device, const SkPaint& paint, - const SkMatrix& matrix, void* storage) const { - SkShader* bitmapShader = this->validInternal(device, paint, matrix, NULL); - if (!bitmapShader) { - return NULL; + SkASSERT(fCachedShader); + if (!fCachedShader->setContext(device, paint, matrix)) { + this->INHERITED::endContext(); + return false; } - return SkNEW_PLACEMENT_ARGS(storage, PictureShaderContext, - (*this, device, paint, matrix, bitmapShader)); + return true; } -size_t SkPictureShader::contextSize() const { - return sizeof(PictureShaderContext); -} - -SkPictureShader::PictureShaderContext::PictureShaderContext( - const SkPictureShader& shader, const SkBitmap& device, - const SkPaint& paint, const SkMatrix& matrix, SkShader* bitmapShader) - : INHERITED(shader, device, paint, matrix) - , fBitmapShader(bitmapShader) -{ - SkASSERT(fBitmapShader); - fBitmapShaderContextStorage = sk_malloc_throw(fBitmapShader->contextSize()); - fBitmapShaderContext = fBitmapShader->createContext( - device, paint, matrix, fBitmapShaderContextStorage); - SkASSERT(fBitmapShaderContext); -} +void SkPictureShader::endContext() { + SkASSERT(fCachedShader); + fCachedShader->endContext(); -SkPictureShader::PictureShaderContext::~PictureShaderContext() { - fBitmapShaderContext->SkShader::Context::~Context(); - sk_free(fBitmapShaderContextStorage); + this->INHERITED::endContext(); } -uint32_t SkPictureShader::PictureShaderContext::getFlags() const { - return fBitmapShaderContext->getFlags(); +uint32_t SkPictureShader::getFlags() { + if (NULL != fCachedShader) { + return fCachedShader->getFlags(); + } + return 0; } -SkShader::Context::ShadeProc SkPictureShader::PictureShaderContext::asAShadeProc(void** ctx) { - return fBitmapShaderContext->asAShadeProc(ctx); +SkShader::ShadeProc SkPictureShader::asAShadeProc(void** ctx) { + if (fCachedShader) { + return fCachedShader->asAShadeProc(ctx); + } + return NULL; } -void SkPictureShader::PictureShaderContext::shadeSpan(int x, int y, SkPMColor dstC[], int count) { - SkASSERT(fBitmapShaderContext); - fBitmapShaderContext->shadeSpan(x, y, dstC, count); +void SkPictureShader::shadeSpan(int x, int y, SkPMColor dstC[], int count) { + SkASSERT(fCachedShader); + fCachedShader->shadeSpan(x, y, dstC, count); } -void SkPictureShader::PictureShaderContext::shadeSpan16(int x, int y, uint16_t dstC[], int count) { - SkASSERT(fBitmapShaderContext); - fBitmapShaderContext->shadeSpan16(x, y, dstC, count); +void SkPictureShader::shadeSpan16(int x, int y, uint16_t dstC[], int count) { + SkASSERT(fCachedShader); + fCachedShader->shadeSpan16(x, y, dstC, count); } #ifndef SK_IGNORE_TO_STRING @@ -209,10 +176,10 @@ void SkPictureShader::toString(SkString* str) const { #if SK_SUPPORT_GPU GrEffectRef* SkPictureShader::asNewEffect(GrContext* context, const SkPaint& paint) const { - SkAutoTUnref<SkShader> bitmapShader(this->buildBitmapShader(context->getMatrix())); - if (!bitmapShader) { + if (!this->buildBitmapShader(context->getMatrix())) { return NULL; } - return bitmapShader->asNewEffect(context, paint); + SkASSERT(fCachedShader); + return fCachedShader->asNewEffect(context, paint); } #endif diff --git a/src/core/SkPictureShader.h b/src/core/SkPictureShader.h index a0a377d0cd..ea74b56d73 100644 --- a/src/core/SkPictureShader.h +++ b/src/core/SkPictureShader.h @@ -24,33 +24,13 @@ public: static SkPictureShader* Create(SkPicture*, TileMode, TileMode); virtual ~SkPictureShader(); - virtual bool validContext(const SkBitmap&, const SkPaint&, - const SkMatrix&, SkMatrix* totalInverse = NULL) const SK_OVERRIDE; - virtual SkShader::Context* createContext(const SkBitmap& device, const SkPaint& paint, - const SkMatrix& matrix, void* storage) const - SK_OVERRIDE; - virtual size_t contextSize() const SK_OVERRIDE; + virtual bool setContext(const SkBitmap&, const SkPaint&, const SkMatrix&) SK_OVERRIDE; + virtual void endContext() SK_OVERRIDE; + virtual uint32_t getFlags() SK_OVERRIDE; - class PictureShaderContext : public SkShader::Context { - public: - PictureShaderContext(const SkPictureShader& shader, const SkBitmap& device, - const SkPaint& paint, const SkMatrix& matrix, - SkShader* bitmapShader); - virtual ~PictureShaderContext(); - - virtual uint32_t getFlags() const SK_OVERRIDE; - - virtual ShadeProc asAShadeProc(void** ctx) SK_OVERRIDE; - virtual void shadeSpan(int x, int y, SkPMColor dstC[], int count) SK_OVERRIDE; - virtual void shadeSpan16(int x, int y, uint16_t dstC[], int count) SK_OVERRIDE; - - private: - SkAutoTUnref<SkShader> fBitmapShader; - SkShader::Context* fBitmapShaderContext; - void* fBitmapShaderContextStorage; - - typedef SkShader::Context INHERITED; - }; + virtual ShadeProc asAShadeProc(void** ctx) SK_OVERRIDE; + virtual void shadeSpan(int x, int y, SkPMColor dstC[], int count) SK_OVERRIDE; + virtual void shadeSpan16(int x, int y, uint16_t dstC[], int count) SK_OVERRIDE; SK_TO_STRING_OVERRIDE() SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkPictureShader) @@ -66,18 +46,13 @@ protected: private: SkPictureShader(SkPicture*, TileMode, TileMode); - SkShader* validInternal(const SkBitmap& device, const SkPaint& paint, - const SkMatrix& matrix, SkMatrix* totalInverse) const; - - SkShader* buildBitmapShader(const SkMatrix&) const; + bool buildBitmapShader(const SkMatrix&) const; SkPicture* fPicture; TileMode fTmx, fTmy; - mutable SkMutex fCachedBitmapShaderMutex; - mutable SkAutoTUnref<SkShader> fCachedBitmapShader; + mutable SkAutoTUnref<SkShader> fCachedShader; mutable SkSize fCachedTileScale; - mutable SkMatrix fCachedLocalMatrix; typedef SkShader INHERITED; }; diff --git a/src/core/SkShader.cpp b/src/core/SkShader.cpp index 40e52a05cb..e337b7d906 100644 --- a/src/core/SkShader.cpp +++ b/src/core/SkShader.cpp @@ -17,6 +17,7 @@ SkShader::SkShader() { fLocalMatrix.reset(); + SkDEBUGCODE(fInSetContext = false;) } SkShader::SkShader(SkReadBuffer& buffer) @@ -26,9 +27,12 @@ SkShader::SkShader(SkReadBuffer& buffer) } else { fLocalMatrix.reset(); } + + SkDEBUGCODE(fInSetContext = false;) } SkShader::~SkShader() { + SkASSERT(!fInSetContext); } void SkShader::flatten(SkWriteBuffer& buffer) const { @@ -40,48 +44,39 @@ void SkShader::flatten(SkWriteBuffer& buffer) const { } } -bool SkShader::computeTotalInverse(const SkMatrix& matrix, SkMatrix* totalInverse) const { +bool SkShader::setContext(const SkBitmap& device, + const SkPaint& paint, + const SkMatrix& matrix) { + SkASSERT(!this->setContextHasBeenCalled()); + const SkMatrix* m = &matrix; SkMatrix total; + fPaintAlpha = paint.getAlpha(); if (this->hasLocalMatrix()) { total.setConcat(matrix, this->getLocalMatrix()); m = &total; } - - return m->invert(totalInverse); -} - -bool SkShader::validContext(const SkBitmap& device, - const SkPaint& paint, - const SkMatrix& matrix, - SkMatrix* totalInverse) const { - return this->computeTotalInverse(matrix, totalInverse); + if (m->invert(&fTotalInverse)) { + fTotalInverseClass = (uint8_t)ComputeMatrixClass(fTotalInverse); + SkDEBUGCODE(fInSetContext = true;) + return true; + } + return false; } -SkShader::Context::Context(const SkShader& shader, const SkBitmap& device, - const SkPaint& paint, const SkMatrix& matrix) - : fShader(shader) -{ - SkASSERT(fShader.validContext(device, paint, matrix)); - - // Because the context parameters must be valid at this point, we know that the matrix is - // invertible. - SkAssertResult(fShader.computeTotalInverse(matrix, &fTotalInverse)); - fTotalInverseClass = (uint8_t)ComputeMatrixClass(fTotalInverse); - - fPaintAlpha = paint.getAlpha(); +void SkShader::endContext() { + SkASSERT(fInSetContext); + SkDEBUGCODE(fInSetContext = false;) } -SkShader::Context::~Context() {} - -SkShader::Context::ShadeProc SkShader::Context::asAShadeProc(void** ctx) { +SkShader::ShadeProc SkShader::asAShadeProc(void** ctx) { return NULL; } #include "SkColorPriv.h" -void SkShader::Context::shadeSpan16(int x, int y, uint16_t span16[], int count) { +void SkShader::shadeSpan16(int x, int y, uint16_t span16[], int count) { SkASSERT(span16); SkASSERT(count > 0); SkASSERT(this->canCallShadeSpan16()); @@ -99,7 +94,7 @@ void SkShader::Context::shadeSpan16(int x, int y, uint16_t span16[], int count) #define SkU32BitShiftToByteOffset(shift) ((shift) >> 3) #endif -void SkShader::Context::shadeSpanAlpha(int x, int y, uint8_t alpha[], int count) { +void SkShader::shadeSpanAlpha(int x, int y, uint8_t alpha[], int count) { SkASSERT(count > 0); SkPMColor colors[kTempColorCount]; @@ -153,7 +148,7 @@ void SkShader::Context::shadeSpanAlpha(int x, int y, uint8_t alpha[], int count) #endif } -SkShader::Context::MatrixClass SkShader::Context::ComputeMatrixClass(const SkMatrix& mat) { +SkShader::MatrixClass SkShader::ComputeMatrixClass(const SkMatrix& mat) { MatrixClass mc = kLinear_MatrixClass; if (mat.hasPerspective()) { @@ -168,7 +163,8 @@ SkShader::Context::MatrixClass SkShader::Context::ComputeMatrixClass(const SkMat ////////////////////////////////////////////////////////////////////////////// -SkShader::BitmapType SkShader::asABitmap(SkBitmap*, SkMatrix*, TileMode*) const { +SkShader::BitmapType SkShader::asABitmap(SkBitmap*, SkMatrix*, + TileMode*) const { return kNone_BitmapType; } @@ -203,16 +199,19 @@ void SkShader::toString(SkString* str) const { #include "SkColorShader.h" #include "SkUtils.h" -SkColorShader::SkColorShader() - : fColor() - , fInheritColor(true) { +SkColorShader::SkColorShader() { + fFlags = 0; + fInheritColor = true; } -SkColorShader::SkColorShader(SkColor c) - : fColor(c) - , fInheritColor(false) { +SkColorShader::SkColorShader(SkColor c) { + fFlags = 0; + fColor = c; + fInheritColor = false; } +SkColorShader::~SkColorShader() {} + bool SkColorShader::isOpaque() const { if (fInheritColor) { return true; // using paint's alpha @@ -221,6 +220,8 @@ bool SkColorShader::isOpaque() const { } SkColorShader::SkColorShader(SkReadBuffer& b) : INHERITED(b) { + fFlags = 0; // computed in setContext + fInheritColor = b.readBool(); if (fInheritColor) { return; @@ -237,43 +238,32 @@ void SkColorShader::flatten(SkWriteBuffer& buffer) const { buffer.writeColor(fColor); } -uint32_t SkColorShader::ColorShaderContext::getFlags() const { +uint32_t SkColorShader::getFlags() { return fFlags; } -uint8_t SkColorShader::ColorShaderContext::getSpan16Alpha() const { +uint8_t SkColorShader::getSpan16Alpha() const { return SkGetPackedA32(fPMColor); } -SkShader::Context* SkColorShader::createContext(const SkBitmap& device, const SkPaint& paint, - const SkMatrix& matrix, void* storage) const { - if (!this->validContext(device, paint, matrix)) { - return NULL; +bool SkColorShader::setContext(const SkBitmap& device, const SkPaint& paint, + const SkMatrix& matrix) { + if (!this->INHERITED::setContext(device, paint, matrix)) { + return false; } - return SkNEW_PLACEMENT_ARGS(storage, ColorShaderContext, (*this, device, paint, matrix)); -} - -SkColorShader::ColorShaderContext::ColorShaderContext(const SkColorShader& shader, - const SkBitmap& device, - const SkPaint& paint, - const SkMatrix& matrix) - : INHERITED(shader, device, paint, matrix) -{ unsigned a; - SkColor color; - if (shader.fInheritColor) { - color = paint.getColor(); - a = SkColorGetA(color); + if (fInheritColor) { + fColor = paint.getColor(); + a = SkColorGetA(fColor); } else { - color = shader.fColor; - a = SkAlphaMul(SkColorGetA(color), SkAlpha255To256(paint.getAlpha())); + a = SkAlphaMul(SkColorGetA(fColor), SkAlpha255To256(paint.getAlpha())); } - unsigned r = SkColorGetR(color); - unsigned g = SkColorGetG(color); - unsigned b = SkColorGetB(color); + unsigned r = SkColorGetR(fColor); + unsigned g = SkColorGetG(fColor); + unsigned b = SkColorGetB(fColor); // we want this before we apply any alpha fColor16 = SkPack888ToRGB16(r, g, b); @@ -292,17 +282,19 @@ SkColorShader::ColorShaderContext::ColorShaderContext(const SkColorShader& shade fFlags |= kHasSpan16_Flag; } } + + return true; } -void SkColorShader::ColorShaderContext::shadeSpan(int x, int y, SkPMColor span[], int count) { +void SkColorShader::shadeSpan(int x, int y, SkPMColor span[], int count) { sk_memset32(span, fPMColor, count); } -void SkColorShader::ColorShaderContext::shadeSpan16(int x, int y, uint16_t span[], int count) { +void SkColorShader::shadeSpan16(int x, int y, uint16_t span[], int count) { sk_memset16(span, fColor16, count); } -void SkColorShader::ColorShaderContext::shadeSpanAlpha(int x, int y, uint8_t alpha[], int count) { +void SkColorShader::shadeSpanAlpha(int x, int y, uint8_t alpha[], int count) { memset(alpha, SkGetPackedA32(fPMColor), count); } @@ -342,9 +334,27 @@ void SkColorShader::toString(SkString* str) const { /////////////////////////////////////////////////////////////////////////////// -#ifndef SK_IGNORE_TO_STRING #include "SkEmptyShader.h" +uint32_t SkEmptyShader::getFlags() { return 0; } +uint8_t SkEmptyShader::getSpan16Alpha() const { return 0; } + +bool SkEmptyShader::setContext(const SkBitmap&, const SkPaint&, + const SkMatrix&) { return false; } + +void SkEmptyShader::shadeSpan(int x, int y, SkPMColor span[], int count) { + SkDEBUGFAIL("should never get called, since setContext() returned false"); +} + +void SkEmptyShader::shadeSpan16(int x, int y, uint16_t span[], int count) { + SkDEBUGFAIL("should never get called, since setContext() returned false"); +} + +void SkEmptyShader::shadeSpanAlpha(int x, int y, uint8_t alpha[], int count) { + SkDEBUGFAIL("should never get called, since setContext() returned false"); +} + +#ifndef SK_IGNORE_TO_STRING void SkEmptyShader::toString(SkString* str) const { str->append("SkEmptyShader: ("); diff --git a/src/core/SkSmallAllocator.h b/src/core/SkSmallAllocator.h index 8d4b53a707..655008b706 100644 --- a/src/core/SkSmallAllocator.h +++ b/src/core/SkSmallAllocator.h @@ -117,12 +117,10 @@ public: // but we're not sure we can catch all callers, so handle it but // assert false in debug mode. SkASSERT(false); - rec->fStorageSize = 0; rec->fHeapStorage = sk_malloc_throw(storageRequired); rec->fObj = static_cast<void*>(rec->fHeapStorage); } else { // There is space in fStorage. - rec->fStorageSize = storageRequired; rec->fHeapStorage = NULL; SkASSERT(SkIsAlign4(fStorageUsed)); rec->fObj = static_cast<void*>(fStorage + (fStorageUsed / 4)); @@ -133,26 +131,11 @@ public: return rec->fObj; } - /* - * Free the memory reserved last without calling the destructor. - * Can be used in a nested way, i.e. after reserving A and B, calling - * freeLast once will free B and calling it again will free A. - */ - void freeLast() { - SkASSERT(fNumObjects > 0); - Rec* rec = &fRecs[fNumObjects - 1]; - sk_free(rec->fHeapStorage); - fStorageUsed -= rec->fStorageSize; - - fNumObjects--; - } - private: struct Rec { - size_t fStorageSize; // 0 if allocated on heap - void* fObj; - void* fHeapStorage; - void (*fKillProc)(void*); + void* fObj; + void* fHeapStorage; + void (*fKillProc)(void*); }; // Number of bytes used so far. diff --git a/src/effects/SkPerlinNoiseShader.cpp b/src/effects/SkPerlinNoiseShader.cpp index 5adb582506..ed63fafae1 100644 --- a/src/effects/SkPerlinNoiseShader.cpp +++ b/src/effects/SkPerlinNoiseShader.cpp @@ -278,6 +278,7 @@ SkPerlinNoiseShader::SkPerlinNoiseShader(SkPerlinNoiseShader::Type type, , fStitchTiles(!fTileSize.isEmpty()) { SkASSERT(numOctaves >= 0 && numOctaves < 256); + fMatrix.reset(); fPaintingData = SkNEW_ARGS(PaintingData, (fTileSize, fSeed, fBaseFrequencyX, fBaseFrequencyY)); } @@ -292,6 +293,7 @@ SkPerlinNoiseShader::SkPerlinNoiseShader(SkReadBuffer& buffer) fStitchTiles = buffer.readBool(); fTileSize.fWidth = buffer.readInt(); fTileSize.fHeight = buffer.readInt(); + fMatrix.reset(); fPaintingData = SkNEW_ARGS(PaintingData, (fTileSize, fSeed, fBaseFrequencyX, fBaseFrequencyY)); buffer.validate(perlin_noise_type_is_valid(fType) && (fNumOctaves >= 0) && (fNumOctaves <= 255) && @@ -315,9 +317,9 @@ void SkPerlinNoiseShader::flatten(SkWriteBuffer& buffer) const { buffer.writeInt(fTileSize.fHeight); } -SkScalar SkPerlinNoiseShader::PerlinNoiseShaderContext::noise2D( - int channel, const PaintingData& paintingData, - const StitchData& stitchData, const SkPoint& noiseVector) const { +SkScalar SkPerlinNoiseShader::noise2D(int channel, const PaintingData& paintingData, + const StitchData& stitchData, + const SkPoint& noiseVector) const { struct Noise { int noisePositionIntegerValue; SkScalar noisePositionFractionValue; @@ -331,9 +333,8 @@ SkScalar SkPerlinNoiseShader::PerlinNoiseShaderContext::noise2D( Noise noiseX(noiseVector.x()); Noise noiseY(noiseVector.y()); SkScalar u, v; - const SkPerlinNoiseShader& perlinNoiseShader = static_cast<const SkPerlinNoiseShader&>(fShader); // If stitching, adjust lattice points accordingly. - if (perlinNoiseShader.fStitchTiles) { + if (fStitchTiles) { noiseX.noisePositionIntegerValue = checkNoise(noiseX.noisePositionIntegerValue, stitchData.fWrapX, stitchData.fWidth); noiseY.noisePositionIntegerValue = @@ -364,11 +365,11 @@ SkScalar SkPerlinNoiseShader::PerlinNoiseShaderContext::noise2D( return SkScalarInterp(a, b, sy); } -SkScalar SkPerlinNoiseShader::PerlinNoiseShaderContext::calculateTurbulenceValueForPoint( - int channel, const PaintingData& paintingData, - StitchData& stitchData, const SkPoint& point) const { - const SkPerlinNoiseShader& perlinNoiseShader = static_cast<const SkPerlinNoiseShader&>(fShader); - if (perlinNoiseShader.fStitchTiles) { +SkScalar SkPerlinNoiseShader::calculateTurbulenceValueForPoint(int channel, + const PaintingData& paintingData, + StitchData& stitchData, + const SkPoint& point) const { + if (fStitchTiles) { // Set up TurbulenceInitial stitch values. stitchData = paintingData.fStitchDataInit; } @@ -376,14 +377,14 @@ SkScalar SkPerlinNoiseShader::PerlinNoiseShaderContext::calculateTurbulenceValue SkPoint noiseVector(SkPoint::Make(SkScalarMul(point.x(), paintingData.fBaseFrequency.fX), SkScalarMul(point.y(), paintingData.fBaseFrequency.fY))); SkScalar ratio = SK_Scalar1; - for (int octave = 0; octave < perlinNoiseShader.fNumOctaves; ++octave) { + for (int octave = 0; octave < fNumOctaves; ++octave) { SkScalar noise = noise2D(channel, paintingData, stitchData, noiseVector); turbulenceFunctionResult += SkScalarDiv( - (perlinNoiseShader.fType == kFractalNoise_Type) ? noise : SkScalarAbs(noise), ratio); + (fType == kFractalNoise_Type) ? noise : SkScalarAbs(noise), ratio); noiseVector.fX *= 2; noiseVector.fY *= 2; ratio *= 2; - if (perlinNoiseShader.fStitchTiles) { + if (fStitchTiles) { // Update stitch values stitchData.fWidth *= 2; stitchData.fWrapX = stitchData.fWidth + kPerlinNoise; @@ -394,7 +395,7 @@ SkScalar SkPerlinNoiseShader::PerlinNoiseShaderContext::calculateTurbulenceValue // The value of turbulenceFunctionResult comes from ((turbulenceFunctionResult) + 1) / 2 // by fractalNoise and (turbulenceFunctionResult) by turbulence. - if (perlinNoiseShader.fType == kFractalNoise_Type) { + if (fType == kFractalNoise_Type) { turbulenceFunctionResult = SkScalarMul(turbulenceFunctionResult, SK_ScalarHalf) + SK_ScalarHalf; } @@ -408,9 +409,7 @@ SkScalar SkPerlinNoiseShader::PerlinNoiseShaderContext::calculateTurbulenceValue return SkScalarPin(turbulenceFunctionResult, 0, SK_Scalar1); } -SkPMColor SkPerlinNoiseShader::PerlinNoiseShaderContext::shade( - const SkPoint& point, StitchData& stitchData) const { - const SkPerlinNoiseShader& perlinNoiseShader = static_cast<const SkPerlinNoiseShader&>(fShader); +SkPMColor SkPerlinNoiseShader::shade(const SkPoint& point, StitchData& stitchData) const { SkPoint newPoint; fMatrix.mapPoints(&newPoint, &point, 1); newPoint.fX = SkScalarRoundToScalar(newPoint.fX); @@ -419,32 +418,15 @@ SkPMColor SkPerlinNoiseShader::PerlinNoiseShaderContext::shade( U8CPU rgba[4]; for (int channel = 3; channel >= 0; --channel) { rgba[channel] = SkScalarFloorToInt(255 * - calculateTurbulenceValueForPoint(channel, *perlinNoiseShader.fPaintingData, - stitchData, newPoint)); + calculateTurbulenceValueForPoint(channel, *fPaintingData, stitchData, newPoint)); } return SkPreMultiplyARGB(rgba[3], rgba[0], rgba[1], rgba[2]); } -SkShader::Context* SkPerlinNoiseShader::createContext(const SkBitmap& device, const SkPaint& paint, - const SkMatrix& matrix, void* storage) const { - if (!this->validContext(device, paint, matrix)) { - return NULL; - } - - return SkNEW_PLACEMENT_ARGS(storage, PerlinNoiseShaderContext, (*this, device, paint, matrix)); -} - -size_t SkPerlinNoiseShader::contextSize() const { - return sizeof(PerlinNoiseShaderContext); -} - -SkPerlinNoiseShader::PerlinNoiseShaderContext::PerlinNoiseShaderContext( - const SkPerlinNoiseShader& shader, const SkBitmap& device, - const SkPaint& paint, const SkMatrix& matrix) - : INHERITED(shader, device, paint, matrix) -{ +bool SkPerlinNoiseShader::setContext(const SkBitmap& device, const SkPaint& paint, + const SkMatrix& matrix) { SkMatrix newMatrix = matrix; - newMatrix.postConcat(shader.getLocalMatrix()); + newMatrix.postConcat(getLocalMatrix()); SkMatrix invMatrix; if (!newMatrix.invert(&invMatrix)) { invMatrix.reset(); @@ -455,10 +437,10 @@ SkPerlinNoiseShader::PerlinNoiseShaderContext::PerlinNoiseShaderContext( newMatrix.postConcat(invMatrix); newMatrix.postConcat(invMatrix); fMatrix = newMatrix; + return INHERITED::setContext(device, paint, matrix); } -void SkPerlinNoiseShader::PerlinNoiseShaderContext::shadeSpan( - int x, int y, SkPMColor result[], int count) { +void SkPerlinNoiseShader::shadeSpan(int x, int y, SkPMColor result[], int count) { SkPoint point = SkPoint::Make(SkIntToScalar(x), SkIntToScalar(y)); StitchData stitchData; for (int i = 0; i < count; ++i) { @@ -467,8 +449,7 @@ void SkPerlinNoiseShader::PerlinNoiseShaderContext::shadeSpan( } } -void SkPerlinNoiseShader::PerlinNoiseShaderContext::shadeSpan16( - int x, int y, uint16_t result[], int count) { +void SkPerlinNoiseShader::shadeSpan16(int x, int y, uint16_t result[], int count) { SkPoint point = SkPoint::Make(SkIntToScalar(x), SkIntToScalar(y)); StitchData stitchData; DITHER_565_SCAN(y); diff --git a/src/effects/SkTransparentShader.cpp b/src/effects/SkTransparentShader.cpp index 0997e62013..bd8b99a3c0 100644 --- a/src/effects/SkTransparentShader.cpp +++ b/src/effects/SkTransparentShader.cpp @@ -11,40 +11,26 @@ #include "SkColorPriv.h" #include "SkString.h" -SkShader::Context* SkTransparentShader::createContext(const SkBitmap& device, - const SkPaint& paint, - const SkMatrix& matrix, - void* storage) const { - if (!this->validContext(device, paint, matrix)) { - return NULL; - } - - return SkNEW_PLACEMENT_ARGS(storage, TransparentShaderContext, (*this, device, paint, matrix)); -} +bool SkTransparentShader::setContext(const SkBitmap& device, + const SkPaint& paint, + const SkMatrix& matrix) { + fDevice = &device; + fAlpha = paint.getAlpha(); -size_t SkTransparentShader::contextSize() const { - return sizeof(TransparentShaderContext); + return this->INHERITED::setContext(device, paint, matrix); } -SkTransparentShader::TransparentShaderContext::TransparentShaderContext( - const SkTransparentShader& shader, const SkBitmap& device, - const SkPaint& paint, const SkMatrix& matrix) - : INHERITED(shader, device, paint, matrix) - , fDevice(&device) {} - -SkTransparentShader::TransparentShaderContext::~TransparentShaderContext() {} - -uint32_t SkTransparentShader::TransparentShaderContext::getFlags() const { +uint32_t SkTransparentShader::getFlags() { uint32_t flags = this->INHERITED::getFlags(); switch (fDevice->colorType()) { case kRGB_565_SkColorType: flags |= kHasSpan16_Flag; - if (this->getPaintAlpha() == 255) + if (fAlpha == 255) flags |= kOpaqueAlpha_Flag; break; case kN32_SkColorType: - if (this->getPaintAlpha() == 255 && fDevice->isOpaque()) + if (fAlpha == 255 && fDevice->isOpaque()) flags |= kOpaqueAlpha_Flag; break; default: @@ -53,9 +39,8 @@ uint32_t SkTransparentShader::TransparentShaderContext::getFlags() const { return flags; } -void SkTransparentShader::TransparentShaderContext::shadeSpan(int x, int y, SkPMColor span[], - int count) { - unsigned scale = SkAlpha255To256(this->getPaintAlpha()); +void SkTransparentShader::shadeSpan(int x, int y, SkPMColor span[], int count) { + unsigned scale = SkAlpha255To256(fAlpha); switch (fDevice->colorType()) { case kN32_SkColorType: @@ -78,7 +63,7 @@ void SkTransparentShader::TransparentShaderContext::shadeSpan(int x, int y, SkPM span[i] = SkPixel16ToPixel32(src[i]); } } else { - unsigned alpha = this->getPaintAlpha(); + unsigned alpha = fAlpha; for (int i = count - 1; i >= 0; --i) { uint16_t c = src[i]; unsigned r = SkPacked16ToR32(c); @@ -112,8 +97,7 @@ void SkTransparentShader::TransparentShaderContext::shadeSpan(int x, int y, SkPM } } -void SkTransparentShader::TransparentShaderContext::shadeSpan16(int x, int y, uint16_t span[], - int count) { +void SkTransparentShader::shadeSpan16(int x, int y, uint16_t span[], int count) { SkASSERT(fDevice->colorType() == kRGB_565_SkColorType); uint16_t* src = fDevice->getAddr16(x, y); diff --git a/src/effects/gradients/SkGradientShader.cpp b/src/effects/gradients/SkGradientShader.cpp index 666204e0ae..2ebb9c71d9 100644 --- a/src/effects/gradients/SkGradientShader.cpp +++ b/src/effects/gradients/SkGradientShader.cpp @@ -15,6 +15,8 @@ SkGradientShaderBase::SkGradientShaderBase(const Descriptor& desc) { SkASSERT(desc.fCount > 1); + fCacheAlpha = 256; // init to a value that paint.getAlpha() can't return + fMapper = desc.fMapper; SkSafeRef(fMapper); fGradFlags = SkToU8(desc.fFlags); @@ -24,6 +26,10 @@ SkGradientShaderBase::SkGradientShaderBase(const Descriptor& desc) { fTileMode = desc.fTileMode; fTileProc = gTileProcs[desc.fTileMode]; + fCache16 = fCache16Storage = NULL; + fCache32 = NULL; + fCache32PixelRef = NULL; + /* Note: we let the caller skip the first and/or last position. i.e. pos[0] = 0.3, pos[1] = 0.7 In these cases, we insert dummy entries to ensure that the final data @@ -138,8 +144,14 @@ static uint32_t unpack_flags(uint32_t packed) { } SkGradientShaderBase::SkGradientShaderBase(SkReadBuffer& buffer) : INHERITED(buffer) { + fCacheAlpha = 256; + fMapper = buffer.readUnitMapper(); + fCache16 = fCache16Storage = NULL; + fCache32 = NULL; + fCache32PixelRef = NULL; + int colorCount = fColorCount = buffer.getArrayCount(); if (colorCount > kColorStorageCount) { size_t allocSize = (sizeof(SkColor) + sizeof(SkPMColor) + sizeof(Rec)) * colorCount; @@ -174,6 +186,10 @@ SkGradientShaderBase::SkGradientShaderBase(SkReadBuffer& buffer) : INHERITED(buf } SkGradientShaderBase::~SkGradientShaderBase() { + if (fCache16Storage) { + sk_free(fCache16Storage); + } + SkSafeUnref(fCache32PixelRef); if (fOrigColors != fStorage) { sk_free(fOrigColors); } @@ -181,6 +197,7 @@ SkGradientShaderBase::~SkGradientShaderBase() { } void SkGradientShaderBase::initCommon() { + fFlags = 0; unsigned colorAlpha = 0xFF; for (int i = 0; i < fColorCount; i++) { colorAlpha &= SkColorGetA(fOrigColors[i]); @@ -207,50 +224,49 @@ bool SkGradientShaderBase::isOpaque() const { return fColorsAreOpaque; } -SkGradientShaderBase::GradientShaderBaseContext::GradientShaderBaseContext( - const SkGradientShaderBase& shader, const SkBitmap& device, - const SkPaint& paint, const SkMatrix& matrix) - : INHERITED(shader, device, paint, matrix) - , fCache(shader.getCache(getPaintAlpha())) -{ - const SkMatrix& inverse = this->getTotalInverse(); +bool SkGradientShaderBase::setContext(const SkBitmap& device, + const SkPaint& paint, + const SkMatrix& matrix) { + if (!this->INHERITED::setContext(device, paint, matrix)) { + return false; + } - fDstToIndex.setConcat(shader.fPtsToUnit, inverse); + const SkMatrix& inverse = this->getTotalInverse(); + fDstToIndex.setConcat(fPtsToUnit, inverse); fDstToIndexProc = fDstToIndex.getMapXYProc(); - fDstToIndexClass = (uint8_t)SkShader::Context::ComputeMatrixClass(fDstToIndex); + fDstToIndexClass = (uint8_t)SkShader::ComputeMatrixClass(fDstToIndex); // now convert our colors in to PMColors unsigned paintAlpha = this->getPaintAlpha(); fFlags = this->INHERITED::getFlags(); - if (shader.fColorsAreOpaque && paintAlpha == 0xFF) { + if (fColorsAreOpaque && paintAlpha == 0xFF) { fFlags |= kOpaqueAlpha_Flag; } // we can do span16 as long as our individual colors are opaque, // regardless of the paint's alpha - if (shader.fColorsAreOpaque) { + if (fColorsAreOpaque) { fFlags |= kHasSpan16_Flag; } -} -SkGradientShaderBase::GradientShaderCache::GradientShaderCache( - U8CPU alpha, const SkGradientShaderBase& shader) - : fCacheAlpha(alpha) - , fShader(shader) - , fCache16Inited(false) - , fCache32Inited(false) -{ - // Only initialize the cache in getCache16/32. - fCache16 = NULL; - fCache32 = NULL; - fCache16Storage = NULL; - fCache32PixelRef = NULL; + this->setCacheAlpha(paintAlpha); + return true; } -SkGradientShaderBase::GradientShaderCache::~GradientShaderCache() { - sk_free(fCache16Storage); - SkSafeUnref(fCache32PixelRef); +void SkGradientShaderBase::setCacheAlpha(U8CPU alpha) const { + // if the new alpha differs from the previous time we were called, inval our cache + // this will trigger the cache to be rebuilt. + // we don't care about the first time, since the cache ptrs will already be NULL + if (fCacheAlpha != alpha) { + fCache16 = NULL; // inval the cache + fCache32 = NULL; // inval the cache + fCacheAlpha = alpha; // record the new alpha + // inform our subclasses + if (fCache32PixelRef) { + fCache32PixelRef->notifyPixelsChanged(); + } + } } #define Fixed_To_Dot8(x) (((x) + 0x80) >> 8) @@ -259,8 +275,8 @@ SkGradientShaderBase::GradientShaderCache::~GradientShaderCache() { build a 16bit table as long as the original colors are opaque, even if the paint specifies a non-opaque alpha. */ -void SkGradientShaderBase::GradientShaderCache::Build16bitCache( - uint16_t cache[], SkColor c0, SkColor c1, int count) { +void SkGradientShaderBase::Build16bitCache(uint16_t cache[], SkColor c0, SkColor c1, + int count) { SkASSERT(count > 1); SkASSERT(SkColorGetA(c0) == 0xFF); SkASSERT(SkColorGetA(c1) == 0xFF); @@ -308,9 +324,8 @@ void SkGradientShaderBase::GradientShaderCache::Build16bitCache( */ typedef uint32_t SkUFixed; -void SkGradientShaderBase::GradientShaderCache::Build32bitCache( - SkPMColor cache[], SkColor c0, SkColor c1, - int count, U8CPU paintAlpha, uint32_t gradFlags) { +void SkGradientShaderBase::Build32bitCache(SkPMColor cache[], SkColor c0, SkColor c1, + int count, U8CPU paintAlpha, uint32_t gradFlags) { SkASSERT(count > 1); // need to apply paintAlpha to our two endpoints @@ -453,121 +468,97 @@ static inline U16CPU bitsTo16(unsigned x, const unsigned bits) { return 0; } -const uint16_t* SkGradientShaderBase::GradientShaderCache::getCache16() { - SkOnce(&fCache16Inited, &fCache16Mutex, SkGradientShaderBase::GradientShaderCache::initCache16, - this); - SkASSERT(fCache16); - return fCache16; -} +const uint16_t* SkGradientShaderBase::getCache16() const { + if (fCache16 == NULL) { + // double the count for dither entries + const int entryCount = kCache16Count * 2; + const size_t allocSize = sizeof(uint16_t) * entryCount; -void SkGradientShaderBase::GradientShaderCache::initCache16(GradientShaderCache* cache) { - // double the count for dither entries - const int entryCount = kCache16Count * 2; - const size_t allocSize = sizeof(uint16_t) * entryCount; - - SkASSERT(NULL == cache->fCache16Storage); - cache->fCache16Storage = (uint16_t*)sk_malloc_throw(allocSize); - cache->fCache16 = cache->fCache16Storage; - if (cache->fShader.fColorCount == 2) { - Build16bitCache(cache->fCache16, cache->fShader.fOrigColors[0], - cache->fShader.fOrigColors[1], kCache16Count); - } else { - Rec* rec = cache->fShader.fRecs; - int prevIndex = 0; - for (int i = 1; i < cache->fShader.fColorCount; i++) { - int nextIndex = SkFixedToFFFF(rec[i].fPos) >> kCache16Shift; - SkASSERT(nextIndex < kCache16Count); - - if (nextIndex > prevIndex) - Build16bitCache(cache->fCache16 + prevIndex, cache->fShader.fOrigColors[i-1], - cache->fShader.fOrigColors[i], nextIndex - prevIndex + 1); - prevIndex = nextIndex; + if (fCache16Storage == NULL) { // set the storage and our working ptr + fCache16Storage = (uint16_t*)sk_malloc_throw(allocSize); + } + fCache16 = fCache16Storage; + if (fColorCount == 2) { + Build16bitCache(fCache16, fOrigColors[0], fOrigColors[1], + kCache16Count); + } else { + Rec* rec = fRecs; + int prevIndex = 0; + for (int i = 1; i < fColorCount; i++) { + int nextIndex = SkFixedToFFFF(rec[i].fPos) >> kCache16Shift; + SkASSERT(nextIndex < kCache16Count); + + if (nextIndex > prevIndex) + Build16bitCache(fCache16 + prevIndex, fOrigColors[i-1], fOrigColors[i], nextIndex - prevIndex + 1); + prevIndex = nextIndex; + } } - } - if (cache->fShader.fMapper) { - cache->fCache16Storage = (uint16_t*)sk_malloc_throw(allocSize); - uint16_t* linear = cache->fCache16; // just computed linear data - uint16_t* mapped = cache->fCache16Storage; // storage for mapped data - SkUnitMapper* map = cache->fShader.fMapper; - for (int i = 0; i < kCache16Count; i++) { - int index = map->mapUnit16(bitsTo16(i, kCache16Bits)) >> kCache16Shift; - mapped[i] = linear[index]; - mapped[i + kCache16Count] = linear[index + kCache16Count]; + if (fMapper) { + fCache16Storage = (uint16_t*)sk_malloc_throw(allocSize); + uint16_t* linear = fCache16; // just computed linear data + uint16_t* mapped = fCache16Storage; // storage for mapped data + SkUnitMapper* map = fMapper; + for (int i = 0; i < kCache16Count; i++) { + int index = map->mapUnit16(bitsTo16(i, kCache16Bits)) >> kCache16Shift; + mapped[i] = linear[index]; + mapped[i + kCache16Count] = linear[index + kCache16Count]; + } + sk_free(fCache16); + fCache16 = fCache16Storage; } - sk_free(cache->fCache16); - cache->fCache16 = cache->fCache16Storage; } + return fCache16; } -const SkPMColor* SkGradientShaderBase::GradientShaderCache::getCache32() { - SkOnce(&fCache32Inited, &fCache32Mutex, SkGradientShaderBase::GradientShaderCache::initCache32, - this); - SkASSERT(fCache32); - return fCache32; -} +const SkPMColor* SkGradientShaderBase::getCache32() const { + if (fCache32 == NULL) { + SkImageInfo info; + info.fWidth = kCache32Count; + info.fHeight = 4; // for our 4 dither rows + info.fAlphaType = kPremul_SkAlphaType; + info.fColorType = kN32_SkColorType; -void SkGradientShaderBase::GradientShaderCache::initCache32(GradientShaderCache* cache) { - SkImageInfo info; - info.fWidth = kCache32Count; - info.fHeight = 4; // for our 4 dither rows - info.fAlphaType = kPremul_SkAlphaType; - info.fColorType = kN32_SkColorType; - - SkASSERT(NULL == cache->fCache32PixelRef); - cache->fCache32PixelRef = SkMallocPixelRef::NewAllocate(info, 0, NULL); - cache->fCache32 = (SkPMColor*)cache->fCache32PixelRef->getAddr(); - if (cache->fShader.fColorCount == 2) { - Build32bitCache(cache->fCache32, cache->fShader.fOrigColors[0], - cache->fShader.fOrigColors[1], kCache32Count, cache->fCacheAlpha, - cache->fShader.fGradFlags); - } else { - Rec* rec = cache->fShader.fRecs; - int prevIndex = 0; - for (int i = 1; i < cache->fShader.fColorCount; i++) { - int nextIndex = SkFixedToFFFF(rec[i].fPos) >> kCache32Shift; - SkASSERT(nextIndex < kCache32Count); - - if (nextIndex > prevIndex) - Build32bitCache(cache->fCache32 + prevIndex, cache->fShader.fOrigColors[i-1], - cache->fShader.fOrigColors[i], nextIndex - prevIndex + 1, - cache->fCacheAlpha, cache->fShader.fGradFlags); - prevIndex = nextIndex; + if (NULL == fCache32PixelRef) { + fCache32PixelRef = SkMallocPixelRef::NewAllocate(info, 0, NULL); } - } - - if (cache->fShader.fMapper) { - SkMallocPixelRef* newPR = SkMallocPixelRef::NewAllocate(info, 0, NULL); - SkPMColor* linear = cache->fCache32; // just computed linear data - SkPMColor* mapped = (SkPMColor*)newPR->getAddr(); // storage for mapped data - SkUnitMapper* map = cache->fShader.fMapper; - for (int i = 0; i < kCache32Count; i++) { - int index = map->mapUnit16((i << 8) | i) >> 8; - mapped[i + kCache32Count*0] = linear[index + kCache32Count*0]; - mapped[i + kCache32Count*1] = linear[index + kCache32Count*1]; - mapped[i + kCache32Count*2] = linear[index + kCache32Count*2]; - mapped[i + kCache32Count*3] = linear[index + kCache32Count*3]; + fCache32 = (SkPMColor*)fCache32PixelRef->getAddr(); + if (fColorCount == 2) { + Build32bitCache(fCache32, fOrigColors[0], fOrigColors[1], + kCache32Count, fCacheAlpha, fGradFlags); + } else { + Rec* rec = fRecs; + int prevIndex = 0; + for (int i = 1; i < fColorCount; i++) { + int nextIndex = SkFixedToFFFF(rec[i].fPos) >> kCache32Shift; + SkASSERT(nextIndex < kCache32Count); + + if (nextIndex > prevIndex) + Build32bitCache(fCache32 + prevIndex, fOrigColors[i-1], + fOrigColors[i], nextIndex - prevIndex + 1, + fCacheAlpha, fGradFlags); + prevIndex = nextIndex; + } } - cache->fCache32PixelRef->unref(); - cache->fCache32PixelRef = newPR; - cache->fCache32 = (SkPMColor*)newPR->getAddr(); - } -} -/* - * The gradient holds a cache for the most recent value of alpha. Successive - * callers with the same alpha value will share the same cache. - */ -SkGradientShaderBase::GradientShaderCache* SkGradientShaderBase::getCache(U8CPU alpha) const { - SkAutoMutexAcquire ama(fCacheMutex); - if (!fCache || fCache->getAlpha() != alpha) { - fCache.reset(SkNEW_ARGS(GradientShaderCache, (alpha, *this))); + if (fMapper) { + SkMallocPixelRef* newPR = SkMallocPixelRef::NewAllocate(info, 0, NULL); + SkPMColor* linear = fCache32; // just computed linear data + SkPMColor* mapped = (SkPMColor*)newPR->getAddr(); // storage for mapped data + SkUnitMapper* map = fMapper; + for (int i = 0; i < kCache32Count; i++) { + int index = map->mapUnit16((i << 8) | i) >> 8; + mapped[i + kCache32Count*0] = linear[index + kCache32Count*0]; + mapped[i + kCache32Count*1] = linear[index + kCache32Count*1]; + mapped[i + kCache32Count*2] = linear[index + kCache32Count*2]; + mapped[i + kCache32Count*3] = linear[index + kCache32Count*3]; + } + fCache32PixelRef->unref(); + fCache32PixelRef = newPR; + fCache32 = (SkPMColor*)newPR->getAddr(); + } } - // Increment the ref counter inside the mutex to ensure the returned pointer is still valid. - // Otherwise, the pointer may have been overwritten on a different thread before the object's - // ref count was incremented. - fCache.get()->ref(); - return fCache; + return fCache32; } /* @@ -581,14 +572,14 @@ SkGradientShaderBase::GradientShaderCache* SkGradientShaderBase::getCache(U8CPU void SkGradientShaderBase::getGradientTableBitmap(SkBitmap* bitmap) const { // our caller assumes no external alpha, so we ensure that our cache is // built with 0xFF - GradientShaderCache* cache = this->getCache(0xFF); + this->setCacheAlpha(0xFF); // don't have a way to put the mapper into our cache-key yet if (fMapper) { - // force our cache32pixelref to be built - (void)cache->getCache32(); + // force our cahce32pixelref to be built + (void)this->getCache32(); bitmap->setConfig(SkImageInfo::MakeN32Premul(kCache32Count, 1)); - bitmap->setPixelRef(cache->getCache32PixelRef()); + bitmap->setPixelRef(fCache32PixelRef); return; } @@ -627,9 +618,9 @@ void SkGradientShaderBase::getGradientTableBitmap(SkBitmap* bitmap) const { if (!gCache->find(storage.get(), size, bitmap)) { // force our cahce32pixelref to be built - (void)cache->getCache32(); + (void)this->getCache32(); bitmap->setConfig(SkImageInfo::MakeN32Premul(kCache32Count, 1)); - bitmap->setPixelRef(cache->getCache32PixelRef()); + bitmap->setPixelRef(fCache32PixelRef); gCache->add(storage.get(), size, *bitmap); } diff --git a/src/effects/gradients/SkGradientShaderPriv.h b/src/effects/gradients/SkGradientShaderPriv.h index e01609462b..83e0789853 100644 --- a/src/effects/gradients/SkGradientShaderPriv.h +++ b/src/effects/gradients/SkGradientShaderPriv.h @@ -19,7 +19,6 @@ #include "SkTemplates.h" #include "SkBitmapCache.h" #include "SkShader.h" -#include "SkOnce.h" static inline void sk_memset32_dither(uint32_t dst[], uint32_t v0, uint32_t v1, int count) { @@ -102,64 +101,8 @@ public: SkGradientShaderBase(const Descriptor& desc); virtual ~SkGradientShaderBase(); - // The cache is initialized on-demand when getCache16/32 is called. - class GradientShaderCache : public SkRefCnt { - public: - GradientShaderCache(U8CPU alpha, const SkGradientShaderBase& shader); - ~GradientShaderCache(); - - const uint16_t* getCache16(); - const SkPMColor* getCache32(); - - SkMallocPixelRef* getCache32PixelRef() const { return fCache32PixelRef; } - - unsigned getAlpha() const { return fCacheAlpha; } - - private: - // Working pointers. If either is NULL, we need to recompute the corresponding cache values. - uint16_t* fCache16; - SkPMColor* fCache32; - - uint16_t* fCache16Storage; // Storage for fCache16, allocated on demand. - SkMallocPixelRef* fCache32PixelRef; - const unsigned fCacheAlpha; // The alpha value we used when we computed the cache. - // Larger than 8bits so we can store uninitialized - // value. - - const SkGradientShaderBase& fShader; - - // Make sure we only initialize the caches once. - bool fCache16Inited, fCache32Inited; - SkMutex fCache16Mutex, fCache32Mutex; - - static void initCache16(GradientShaderCache* cache); - static void initCache32(GradientShaderCache* cache); - - static void Build16bitCache(uint16_t[], SkColor c0, SkColor c1, int count); - static void Build32bitCache(SkPMColor[], SkColor c0, SkColor c1, int count, - U8CPU alpha, uint32_t gradFlags); - }; - - class GradientShaderBaseContext : public SkShader::Context { - public: - GradientShaderBaseContext(const SkGradientShaderBase& shader, const SkBitmap& device, - const SkPaint& paint, const SkMatrix& matrix); - ~GradientShaderBaseContext() {} - - virtual uint32_t getFlags() const SK_OVERRIDE { return fFlags; } - - protected: - SkMatrix fDstToIndex; - SkMatrix::MapXYProc fDstToIndexProc; - uint8_t fDstToIndexClass; - uint8_t fFlags; - - SkAutoTUnref<GradientShaderCache> fCache; - - private: - typedef SkShader::Context INHERITED; - }; - + virtual bool setContext(const SkBitmap&, const SkPaint&, const SkMatrix&) SK_OVERRIDE; + virtual uint32_t getFlags() SK_OVERRIDE { return fFlags; } virtual bool isOpaque() const SK_OVERRIDE; void getGradientTableBitmap(SkBitmap*) const; @@ -185,6 +128,7 @@ public: kDitherStride16 = kCache16Count, }; + protected: SkGradientShaderBase(SkReadBuffer& ); virtual void flatten(SkWriteBuffer&) const SK_OVERRIDE; @@ -192,9 +136,13 @@ protected: SkUnitMapper* fMapper; SkMatrix fPtsToUnit; // set by subclass + SkMatrix fDstToIndex; + SkMatrix::MapXYProc fDstToIndexProc; TileMode fTileMode; TileProc fTileProc; int fColorCount; + uint8_t fDstToIndexClass; + uint8_t fFlags; uint8_t fGradFlags; struct Rec { @@ -203,6 +151,9 @@ protected: }; Rec* fRecs; + const uint16_t* getCache16() const; + const SkPMColor* getCache32() const; + void commonAsAGradient(GradientInfo*) const; private: @@ -212,13 +163,20 @@ private: kStorageSize = kColorStorageCount * (sizeof(SkColor) + sizeof(Rec)) }; SkColor fStorage[(kStorageSize + 3) >> 2]; - SkColor* fOrigColors; // original colors, before modulation by paint in context. + SkColor* fOrigColors; // original colors, before modulation by paint in setContext bool fColorsAreOpaque; - GradientShaderCache* getCache(U8CPU alpha) const; - mutable SkMutex fCacheMutex; - mutable SkAutoTUnref<GradientShaderCache> fCache; + mutable uint16_t* fCache16; // working ptr. If this is NULL, we need to recompute the cache values + mutable SkPMColor* fCache32; // working ptr. If this is NULL, we need to recompute the cache values + + mutable uint16_t* fCache16Storage; // storage for fCache16, allocated on demand + mutable SkMallocPixelRef* fCache32PixelRef; + mutable unsigned fCacheAlpha; // the alpha value we used when we computed the cache. larger than 8bits so we can store uninitialized value + static void Build16bitCache(uint16_t[], SkColor c0, SkColor c1, int count); + static void Build32bitCache(SkPMColor[], SkColor c0, SkColor c1, int count, + U8CPU alpha, uint32_t gradFlags); + void setCacheAlpha(U8CPU alpha) const; void initCommon(); typedef SkShader INHERITED; diff --git a/src/effects/gradients/SkLinearGradient.cpp b/src/effects/gradients/SkLinearGradient.cpp index e660d7cd2d..b24a6349c7 100644 --- a/src/effects/gradients/SkLinearGradient.cpp +++ b/src/effects/gradients/SkLinearGradient.cpp @@ -71,24 +71,12 @@ void SkLinearGradient::flatten(SkWriteBuffer& buffer) const { buffer.writePoint(fEnd); } -size_t SkLinearGradient::contextSize() const { - return sizeof(LinearGradientContext); -} - -SkShader::Context* SkLinearGradient::createContext(const SkBitmap& device, const SkPaint& paint, - const SkMatrix& matrix, void* storage) const { - if (!this->validContext(device, paint, matrix)) { - return NULL; +bool SkLinearGradient::setContext(const SkBitmap& device, const SkPaint& paint, + const SkMatrix& matrix) { + if (!this->INHERITED::setContext(device, paint, matrix)) { + return false; } - return SkNEW_PLACEMENT_ARGS(storage, LinearGradientContext, (*this, device, paint, matrix)); -} - -SkLinearGradient::LinearGradientContext::LinearGradientContext( - const SkLinearGradient& shader, const SkBitmap& device, - const SkPaint& paint, const SkMatrix& matrix) - : INHERITED(shader, device, paint, matrix) -{ unsigned mask = SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask; if ((fDstToIndex.getType() & ~mask) == 0) { // when we dither, we are (usually) not const-in-Y @@ -99,6 +87,7 @@ SkLinearGradient::LinearGradientContext::LinearGradientContext( fFlags |= SkShader::kConstInY16_Flag; } } + return true; } #define NO_CHECK_ITER \ @@ -207,16 +196,14 @@ void shadeSpan_linear_repeat(TileProc proc, SkFixed dx, SkFixed fx, } -void SkLinearGradient::LinearGradientContext::shadeSpan(int x, int y, SkPMColor* SK_RESTRICT dstC, - int count) { +void SkLinearGradient::shadeSpan(int x, int y, SkPMColor* SK_RESTRICT dstC, + int count) { SkASSERT(count > 0); - const SkLinearGradient& linearGradient = static_cast<const SkLinearGradient&>(fShader); - SkPoint srcPt; SkMatrix::MapXYProc dstProc = fDstToIndexProc; - TileProc proc = linearGradient.fTileProc; - const SkPMColor* SK_RESTRICT cache = fCache->getCache32(); + TileProc proc = fTileProc; + const SkPMColor* SK_RESTRICT cache = this->getCache32(); int toggle = init_dither_toggle(x, y); if (fDstToIndexClass != kPerspective_MatrixClass) { @@ -236,12 +223,12 @@ void SkLinearGradient::LinearGradientContext::shadeSpan(int x, int y, SkPMColor* LinearShadeProc shadeProc = shadeSpan_linear_repeat; if (0 == dx) { shadeProc = shadeSpan_linear_vertical_lerp; - } else if (SkShader::kClamp_TileMode == linearGradient.fTileMode) { + } else if (SkShader::kClamp_TileMode == fTileMode) { shadeProc = shadeSpan_linear_clamp; - } else if (SkShader::kMirror_TileMode == linearGradient.fTileMode) { + } else if (SkShader::kMirror_TileMode == fTileMode) { shadeProc = shadeSpan_linear_mirror; } else { - SkASSERT(SkShader::kRepeat_TileMode == linearGradient.fTileMode); + SkASSERT(SkShader::kRepeat_TileMode == fTileMode); } (*shadeProc)(proc, dx, fx, dstC, cache, toggle, count); } else { @@ -394,16 +381,14 @@ static bool fixed_nearly_zero(SkFixed x) { return SkAbs32(x) < (SK_Fixed1 >> 12); } -void SkLinearGradient::LinearGradientContext::shadeSpan16(int x, int y, - uint16_t* SK_RESTRICT dstC, int count) { +void SkLinearGradient::shadeSpan16(int x, int y, + uint16_t* SK_RESTRICT dstC, int count) { SkASSERT(count > 0); - const SkLinearGradient& linearGradient = static_cast<const SkLinearGradient&>(fShader); - SkPoint srcPt; SkMatrix::MapXYProc dstProc = fDstToIndexProc; - TileProc proc = linearGradient.fTileProc; - const uint16_t* SK_RESTRICT cache = fCache->getCache16(); + TileProc proc = fTileProc; + const uint16_t* SK_RESTRICT cache = this->getCache16(); int toggle = init_dither_toggle16(x, y); if (fDstToIndexClass != kPerspective_MatrixClass) { @@ -423,12 +408,12 @@ void SkLinearGradient::LinearGradientContext::shadeSpan16(int x, int y, LinearShade16Proc shadeProc = shadeSpan16_linear_repeat; if (fixed_nearly_zero(dx)) { shadeProc = shadeSpan16_linear_vertical; - } else if (SkShader::kClamp_TileMode == linearGradient.fTileMode) { + } else if (SkShader::kClamp_TileMode == fTileMode) { shadeProc = shadeSpan16_linear_clamp; - } else if (SkShader::kMirror_TileMode == linearGradient.fTileMode) { + } else if (SkShader::kMirror_TileMode == fTileMode) { shadeProc = shadeSpan16_linear_mirror; } else { - SkASSERT(SkShader::kRepeat_TileMode == linearGradient.fTileMode); + SkASSERT(SkShader::kRepeat_TileMode == fTileMode); } (*shadeProc)(proc, dx, fx, dstC, cache, toggle, count); } else { diff --git a/src/effects/gradients/SkLinearGradient.h b/src/effects/gradients/SkLinearGradient.h index 8d806672f8..013c4499b0 100644 --- a/src/effects/gradients/SkLinearGradient.h +++ b/src/effects/gradients/SkLinearGradient.h @@ -15,23 +15,9 @@ class SkLinearGradient : public SkGradientShaderBase { public: SkLinearGradient(const SkPoint pts[2], const Descriptor&); - virtual SkShader::Context* createContext(const SkBitmap&, const SkPaint&, const SkMatrix&, - void* storage) const SK_OVERRIDE; - virtual size_t contextSize() const SK_OVERRIDE; - - class LinearGradientContext : public SkGradientShaderBase::GradientShaderBaseContext { - public: - LinearGradientContext(const SkLinearGradient& shader, const SkBitmap& device, - const SkPaint& paint, const SkMatrix& matrix); - ~LinearGradientContext() {} - - virtual void shadeSpan(int x, int y, SkPMColor dstC[], int count) SK_OVERRIDE; - virtual void shadeSpan16(int x, int y, uint16_t dstC[], int count) SK_OVERRIDE; - - private: - typedef SkGradientShaderBase::GradientShaderBaseContext INHERITED; - }; - + virtual bool setContext(const SkBitmap&, const SkPaint&, const SkMatrix&) SK_OVERRIDE; + virtual void shadeSpan(int x, int y, SkPMColor dstC[], int count) SK_OVERRIDE; + virtual void shadeSpan16(int x, int y, uint16_t dstC[], int count) SK_OVERRIDE; virtual BitmapType asABitmap(SkBitmap*, SkMatrix*, TileMode*) const SK_OVERRIDE; virtual GradientType asAGradient(GradientInfo* info) const SK_OVERRIDE; virtual GrEffectRef* asNewEffect(GrContext* context, const SkPaint&) const SK_OVERRIDE; diff --git a/src/effects/gradients/SkRadialGradient.cpp b/src/effects/gradients/SkRadialGradient.cpp index bc2ea3b92b..1b9e7258c4 100644 --- a/src/effects/gradients/SkRadialGradient.cpp +++ b/src/effects/gradients/SkRadialGradient.cpp @@ -157,36 +157,16 @@ SkRadialGradient::SkRadialGradient(const SkPoint& center, SkScalar radius, rad_to_unit_matrix(center, radius, &fPtsToUnit); } -size_t SkRadialGradient::contextSize() const { - return sizeof(RadialGradientContext); -} - -SkShader::Context* SkRadialGradient::createContext(const SkBitmap& device, const SkPaint& paint, - const SkMatrix& matrix, void* storage) const { - if (!this->validContext(device, paint, matrix)) { - return NULL; - } - - return SkNEW_PLACEMENT_ARGS(storage, RadialGradientContext, (*this, device, paint, matrix)); -} - -SkRadialGradient::RadialGradientContext::RadialGradientContext( - const SkRadialGradient& shader, const SkBitmap& device, - const SkPaint& paint, const SkMatrix& matrix) - : INHERITED(shader, device, paint, matrix) {} - -void SkRadialGradient::RadialGradientContext::shadeSpan16(int x, int y, uint16_t* dstCParam, - int count) { +void SkRadialGradient::shadeSpan16(int x, int y, uint16_t* dstCParam, + int count) { SkASSERT(count > 0); - const SkRadialGradient& radialGradient = static_cast<const SkRadialGradient&>(fShader); - uint16_t* SK_RESTRICT dstC = dstCParam; SkPoint srcPt; SkMatrix::MapXYProc dstProc = fDstToIndexProc; - TileProc proc = radialGradient.fTileProc; - const uint16_t* SK_RESTRICT cache = fCache->getCache16(); + TileProc proc = fTileProc; + const uint16_t* SK_RESTRICT cache = this->getCache16(); int toggle = init_dither_toggle16(x, y); if (fDstToIndexClass != kPerspective_MatrixClass) { @@ -207,12 +187,12 @@ void SkRadialGradient::RadialGradientContext::shadeSpan16(int x, int y, uint16_t } RadialShade16Proc shadeProc = shadeSpan16_radial_repeat; - if (SkShader::kClamp_TileMode == radialGradient.fTileMode) { + if (SkShader::kClamp_TileMode == fTileMode) { shadeProc = shadeSpan16_radial_clamp; - } else if (SkShader::kMirror_TileMode == radialGradient.fTileMode) { + } else if (SkShader::kMirror_TileMode == fTileMode) { shadeProc = shadeSpan16_radial_mirror; } else { - SkASSERT(SkShader::kRepeat_TileMode == radialGradient.fTileMode); + SkASSERT(SkShader::kRepeat_TileMode == fTileMode); } (*shadeProc)(srcPt.fX, sdx, srcPt.fY, sdy, dstC, cache, toggle, count); @@ -409,16 +389,14 @@ void shadeSpan_radial_repeat(SkScalar fx, SkScalar dx, SkScalar fy, SkScalar dy, } // namespace -void SkRadialGradient::RadialGradientContext::shadeSpan(int x, int y, - SkPMColor* SK_RESTRICT dstC, int count) { +void SkRadialGradient::shadeSpan(int x, int y, + SkPMColor* SK_RESTRICT dstC, int count) { SkASSERT(count > 0); - const SkRadialGradient& radialGradient = static_cast<const SkRadialGradient&>(fShader); - SkPoint srcPt; SkMatrix::MapXYProc dstProc = fDstToIndexProc; - TileProc proc = radialGradient.fTileProc; - const SkPMColor* SK_RESTRICT cache = fCache->getCache32(); + TileProc proc = fTileProc; + const SkPMColor* SK_RESTRICT cache = this->getCache32(); int toggle = init_dither_toggle(x, y); if (fDstToIndexClass != kPerspective_MatrixClass) { @@ -438,12 +416,12 @@ void SkRadialGradient::RadialGradientContext::shadeSpan(int x, int y, } RadialShadeProc shadeProc = shadeSpan_radial_repeat; - if (SkShader::kClamp_TileMode == radialGradient.fTileMode) { + if (SkShader::kClamp_TileMode == fTileMode) { shadeProc = shadeSpan_radial_clamp; - } else if (SkShader::kMirror_TileMode == radialGradient.fTileMode) { + } else if (SkShader::kMirror_TileMode == fTileMode) { shadeProc = shadeSpan_radial_mirror; } else { - SkASSERT(SkShader::kRepeat_TileMode == radialGradient.fTileMode); + SkASSERT(SkShader::kRepeat_TileMode == fTileMode); } (*shadeProc)(srcPt.fX, sdx, srcPt.fY, sdy, dstC, cache, count, toggle); } else { // perspective case diff --git a/src/effects/gradients/SkRadialGradient.h b/src/effects/gradients/SkRadialGradient.h index a3d04b1aaf..4a725145b0 100644 --- a/src/effects/gradients/SkRadialGradient.h +++ b/src/effects/gradients/SkRadialGradient.h @@ -14,24 +14,10 @@ class SkRadialGradient : public SkGradientShaderBase { public: SkRadialGradient(const SkPoint& center, SkScalar radius, const Descriptor&); - - virtual SkShader::Context* createContext(const SkBitmap&, const SkPaint&, const SkMatrix&, - void* storage) const SK_OVERRIDE; - virtual size_t contextSize() const SK_OVERRIDE; - - class RadialGradientContext : public SkGradientShaderBase::GradientShaderBaseContext { - public: - RadialGradientContext(const SkRadialGradient& shader, const SkBitmap& device, - const SkPaint& paint, const SkMatrix& matrix); - ~RadialGradientContext() {} - - virtual void shadeSpan(int x, int y, SkPMColor dstC[], int count) SK_OVERRIDE; - virtual void shadeSpan16(int x, int y, uint16_t dstC[], int count) SK_OVERRIDE; - - private: - typedef SkGradientShaderBase::GradientShaderBaseContext INHERITED; - }; - + virtual void shadeSpan(int x, int y, SkPMColor* dstC, int count) + SK_OVERRIDE; + virtual void shadeSpan16(int x, int y, uint16_t* dstCParam, + int count) SK_OVERRIDE; virtual BitmapType asABitmap(SkBitmap* bitmap, SkMatrix* matrix, TileMode* xy) const SK_OVERRIDE; diff --git a/src/effects/gradients/SkSweepGradient.cpp b/src/effects/gradients/SkSweepGradient.cpp index 6dff1e71cd..7024945bf0 100644 --- a/src/effects/gradients/SkSweepGradient.cpp +++ b/src/effects/gradients/SkSweepGradient.cpp @@ -52,24 +52,6 @@ void SkSweepGradient::flatten(SkWriteBuffer& buffer) const { buffer.writePoint(fCenter); } -size_t SkSweepGradient::contextSize() const { - return sizeof(SweepGradientContext); -} - -SkShader::Context* SkSweepGradient::createContext(const SkBitmap& device, const SkPaint& paint, - const SkMatrix& matrix, void* storage) const { - if (!this->validContext(device, paint, matrix)) { - return NULL; - } - - return SkNEW_PLACEMENT_ARGS(storage, SweepGradientContext, (*this, device, paint, matrix)); -} - -SkSweepGradient::SweepGradientContext::SweepGradientContext( - const SkSweepGradient& shader, const SkBitmap& device, - const SkPaint& paint, const SkMatrix& matrix) - : INHERITED(shader, device, paint, matrix) {} - // returns angle in a circle [0..2PI) -> [0..255] static unsigned SkATan2_255(float y, float x) { // static const float g255Over2PI = 255 / (2 * SK_ScalarPI); @@ -87,11 +69,11 @@ static unsigned SkATan2_255(float y, float x) { return ir; } -void SkSweepGradient::SweepGradientContext::shadeSpan(int x, int y, SkPMColor* SK_RESTRICT dstC, - int count) { +void SkSweepGradient::shadeSpan(int x, int y, SkPMColor* SK_RESTRICT dstC, + int count) { SkMatrix::MapXYProc proc = fDstToIndexProc; const SkMatrix& matrix = fDstToIndex; - const SkPMColor* SK_RESTRICT cache = fCache->getCache32(); + const SkPMColor* SK_RESTRICT cache = this->getCache32(); int toggle = init_dither_toggle(x, y); SkPoint srcPt; @@ -129,11 +111,11 @@ void SkSweepGradient::SweepGradientContext::shadeSpan(int x, int y, SkPMColor* S } } -void SkSweepGradient::SweepGradientContext::shadeSpan16(int x, int y, uint16_t* SK_RESTRICT dstC, - int count) { +void SkSweepGradient::shadeSpan16(int x, int y, uint16_t* SK_RESTRICT dstC, + int count) { SkMatrix::MapXYProc proc = fDstToIndexProc; const SkMatrix& matrix = fDstToIndex; - const uint16_t* SK_RESTRICT cache = fCache->getCache16(); + const uint16_t* SK_RESTRICT cache = this->getCache16(); int toggle = init_dither_toggle16(x, y); SkPoint srcPt; diff --git a/src/effects/gradients/SkSweepGradient.h b/src/effects/gradients/SkSweepGradient.h index 9998ed16a7..ca19da25ba 100644 --- a/src/effects/gradients/SkSweepGradient.h +++ b/src/effects/gradients/SkSweepGradient.h @@ -14,23 +14,8 @@ class SkSweepGradient : public SkGradientShaderBase { public: SkSweepGradient(SkScalar cx, SkScalar cy, const Descriptor&); - - virtual SkShader::Context* createContext(const SkBitmap&, const SkPaint&, const SkMatrix&, - void* storage) const SK_OVERRIDE; - virtual size_t contextSize() const SK_OVERRIDE; - - class SweepGradientContext : public SkGradientShaderBase::GradientShaderBaseContext { - public: - SweepGradientContext(const SkSweepGradient& shader, const SkBitmap& device, - const SkPaint& paint, const SkMatrix& matrix); - ~SweepGradientContext() {} - - virtual void shadeSpan(int x, int y, SkPMColor dstC[], int count) SK_OVERRIDE; - virtual void shadeSpan16(int x, int y, uint16_t dstC[], int count) SK_OVERRIDE; - - private: - typedef SkGradientShaderBase::GradientShaderBaseContext INHERITED; - }; + virtual void shadeSpan(int x, int y, SkPMColor dstC[], int count) SK_OVERRIDE; + virtual void shadeSpan16(int x, int y, uint16_t dstC[], int count) SK_OVERRIDE; virtual BitmapType asABitmap(SkBitmap* bitmap, SkMatrix* matrix, @@ -48,9 +33,8 @@ protected: virtual void flatten(SkWriteBuffer& buffer) const SK_OVERRIDE; private: - const SkPoint fCenter; - typedef SkGradientShaderBase INHERITED; + const SkPoint fCenter; }; #endif diff --git a/src/effects/gradients/SkTwoPointConicalGradient.cpp b/src/effects/gradients/SkTwoPointConicalGradient.cpp index b0955a2583..de8c2364c3 100644 --- a/src/effects/gradients/SkTwoPointConicalGradient.cpp +++ b/src/effects/gradients/SkTwoPointConicalGradient.cpp @@ -9,18 +9,6 @@ #include "SkTwoPointConicalGradient_gpu.h" -struct TwoPtRadialContext { - const TwoPtRadial& fRec; - float fRelX, fRelY; - const float fIncX, fIncY; - float fB; - const float fDB; - - TwoPtRadialContext(const TwoPtRadial& rec, SkScalar fx, SkScalar fy, - SkScalar dfx, SkScalar dfy); - SkFixed nextT(); -}; - static int valid_divide(float numer, float denom, float* ratio) { SkASSERT(ratio); if (0 == denom) { @@ -89,48 +77,47 @@ void TwoPtRadial::init(const SkPoint& center0, SkScalar rad0, fRDR = fRadius * fDRadius; } -TwoPtRadialContext::TwoPtRadialContext(const TwoPtRadial& rec, SkScalar fx, SkScalar fy, - SkScalar dfx, SkScalar dfy) - : fRec(rec) - , fRelX(SkScalarToFloat(fx) - rec.fCenterX) - , fRelY(SkScalarToFloat(fy) - rec.fCenterY) - , fIncX(SkScalarToFloat(dfx)) - , fIncY(SkScalarToFloat(dfy)) - , fB(-2 * (rec.fDCenterX * fRelX + rec.fDCenterY * fRelY + rec.fRDR)) - , fDB(-2 * (rec.fDCenterX * fIncX + rec.fDCenterY * fIncY)) {} - -SkFixed TwoPtRadialContext::nextT() { +void TwoPtRadial::setup(SkScalar fx, SkScalar fy, SkScalar dfx, SkScalar dfy) { + fRelX = SkScalarToFloat(fx) - fCenterX; + fRelY = SkScalarToFloat(fy) - fCenterY; + fIncX = SkScalarToFloat(dfx); + fIncY = SkScalarToFloat(dfy); + fB = -2 * (fDCenterX * fRelX + fDCenterY * fRelY + fRDR); + fDB = -2 * (fDCenterX * fIncX + fDCenterY * fIncY); +} + +SkFixed TwoPtRadial::nextT() { float roots[2]; - float C = sqr(fRelX) + sqr(fRelY) - fRec.fRadius2; - int countRoots = find_quad_roots(fRec.fA, fB, C, roots); + float C = sqr(fRelX) + sqr(fRelY) - fRadius2; + int countRoots = find_quad_roots(fA, fB, C, roots); fRelX += fIncX; fRelY += fIncY; fB += fDB; if (0 == countRoots) { - return TwoPtRadial::kDontDrawT; + return kDontDrawT; } // Prefer the bigger t value if both give a radius(t) > 0 // find_quad_roots returns the values sorted, so we start with the last float t = roots[countRoots - 1]; - float r = lerp(fRec.fRadius, fRec.fDRadius, t); + float r = lerp(fRadius, fDRadius, t); if (r <= 0) { t = roots[0]; // might be the same as roots[countRoots-1] - r = lerp(fRec.fRadius, fRec.fDRadius, t); + r = lerp(fRadius, fDRadius, t); if (r <= 0) { - return TwoPtRadial::kDontDrawT; + return kDontDrawT; } } return SkFloatToFixed(t); } -typedef void (*TwoPointConicalProc)(TwoPtRadialContext* rec, SkPMColor* dstC, +typedef void (*TwoPointConicalProc)(TwoPtRadial* rec, SkPMColor* dstC, const SkPMColor* cache, int toggle, int count); -static void twopoint_clamp(TwoPtRadialContext* rec, SkPMColor* SK_RESTRICT dstC, +static void twopoint_clamp(TwoPtRadial* rec, SkPMColor* SK_RESTRICT dstC, const SkPMColor* SK_RESTRICT cache, int toggle, int count) { for (; count > 0; --count) { @@ -147,7 +134,7 @@ static void twopoint_clamp(TwoPtRadialContext* rec, SkPMColor* SK_RESTRICT dstC, } } -static void twopoint_repeat(TwoPtRadialContext* rec, SkPMColor* SK_RESTRICT dstC, +static void twopoint_repeat(TwoPtRadial* rec, SkPMColor* SK_RESTRICT dstC, const SkPMColor* SK_RESTRICT cache, int toggle, int count) { for (; count > 0; --count) { @@ -164,7 +151,7 @@ static void twopoint_repeat(TwoPtRadialContext* rec, SkPMColor* SK_RESTRICT dstC } } -static void twopoint_mirror(TwoPtRadialContext* rec, SkPMColor* SK_RESTRICT dstC, +static void twopoint_mirror(TwoPtRadial* rec, SkPMColor* SK_RESTRICT dstC, const SkPMColor* SK_RESTRICT cache, int toggle, int count) { for (; count > 0; --count) { @@ -209,39 +196,8 @@ bool SkTwoPointConicalGradient::isOpaque() const { return false; } -size_t SkTwoPointConicalGradient::contextSize() const { - return sizeof(TwoPointConicalGradientContext); -} - -SkShader::Context* SkTwoPointConicalGradient::createContext( - const SkBitmap& device, const SkPaint& paint, - const SkMatrix& matrix, void* storage) const { - if (!this->validContext(device, paint, matrix)) { - return NULL; - } - - return SkNEW_PLACEMENT_ARGS(storage, TwoPointConicalGradientContext, - (*this, device, paint, matrix)); -} - -SkTwoPointConicalGradient::TwoPointConicalGradientContext::TwoPointConicalGradientContext( - const SkTwoPointConicalGradient& shader, const SkBitmap& device, - const SkPaint& paint, const SkMatrix& matrix) - : INHERITED(shader, device, paint, matrix) -{ - // we don't have a span16 proc - fFlags &= ~kHasSpan16_Flag; - - // in general, we might discard based on computed-radius, so clear - // this flag (todo: sometimes we can detect that we never discard...) - fFlags &= ~kOpaqueAlpha_Flag; -} - -void SkTwoPointConicalGradient::TwoPointConicalGradientContext::shadeSpan( - int x, int y, SkPMColor* dstCParam, int count) { - const SkTwoPointConicalGradient& twoPointConicalGradient = - static_cast<const SkTwoPointConicalGradient&>(fShader); - +void SkTwoPointConicalGradient::shadeSpan(int x, int y, SkPMColor* dstCParam, + int count) { int toggle = init_dither_toggle(x, y); SkASSERT(count > 0); @@ -250,15 +206,15 @@ void SkTwoPointConicalGradient::TwoPointConicalGradientContext::shadeSpan( SkMatrix::MapXYProc dstProc = fDstToIndexProc; - const SkPMColor* SK_RESTRICT cache = fCache->getCache32(); + const SkPMColor* SK_RESTRICT cache = this->getCache32(); TwoPointConicalProc shadeProc = twopoint_repeat; - if (SkShader::kClamp_TileMode == twoPointConicalGradient.fTileMode) { + if (SkShader::kClamp_TileMode == fTileMode) { shadeProc = twopoint_clamp; - } else if (SkShader::kMirror_TileMode == twoPointConicalGradient.fTileMode) { + } else if (SkShader::kMirror_TileMode == fTileMode) { shadeProc = twopoint_mirror; } else { - SkASSERT(SkShader::kRepeat_TileMode == twoPointConicalGradient.fTileMode); + SkASSERT(SkShader::kRepeat_TileMode == fTileMode); } if (fDstToIndexClass != kPerspective_MatrixClass) { @@ -279,16 +235,16 @@ void SkTwoPointConicalGradient::TwoPointConicalGradientContext::shadeSpan( dy = fDstToIndex.getSkewY(); } - TwoPtRadialContext rec(twoPointConicalGradient.fRec, fx, fy, dx, dy); - (*shadeProc)(&rec, dstC, cache, toggle, count); + fRec.setup(fx, fy, dx, dy); + (*shadeProc)(&fRec, dstC, cache, toggle, count); } else { // perspective case SkScalar dstX = SkIntToScalar(x) + SK_ScalarHalf; SkScalar dstY = SkIntToScalar(y) + SK_ScalarHalf; for (; count > 0; --count) { SkPoint srcPt; dstProc(fDstToIndex, dstX, dstY, &srcPt); - TwoPtRadialContext rec(twoPointConicalGradient.fRec, srcPt.fX, srcPt.fY, 0, 0); - (*shadeProc)(&rec, dstC, cache, toggle, 1); + fRec.setup(srcPt.fX, srcPt.fY, 0, 0); + (*shadeProc)(&fRec, dstC, cache, toggle, 1); dstX += SK_Scalar1; toggle = next_dither_toggle(toggle); @@ -297,6 +253,23 @@ void SkTwoPointConicalGradient::TwoPointConicalGradientContext::shadeSpan( } } +bool SkTwoPointConicalGradient::setContext(const SkBitmap& device, + const SkPaint& paint, + const SkMatrix& matrix) { + if (!this->INHERITED::setContext(device, paint, matrix)) { + return false; + } + + // we don't have a span16 proc + fFlags &= ~kHasSpan16_Flag; + + // in general, we might discard based on computed-radius, so clear + // this flag (todo: sometimes we can detect that we never discard...) + fFlags &= ~kOpaqueAlpha_Flag; + + return true; +} + SkShader::BitmapType SkTwoPointConicalGradient::asABitmap( SkBitmap* bitmap, SkMatrix* matrix, SkShader::TileMode* xy) const { SkPoint diff = fCenter2 - fCenter1; diff --git a/src/effects/gradients/SkTwoPointConicalGradient.h b/src/effects/gradients/SkTwoPointConicalGradient.h index 4c049172d3..041f8b8be4 100644 --- a/src/effects/gradients/SkTwoPointConicalGradient.h +++ b/src/effects/gradients/SkTwoPointConicalGradient.h @@ -11,8 +11,6 @@ #include "SkGradientShaderPriv.h" -// TODO(dominikg): Worth making it truly immutable (i.e. set values in constructor)? -// Should only be initialized once via init(). Immutable afterwards. struct TwoPtRadial { enum { kDontDrawT = 0x80000000 @@ -29,6 +27,13 @@ struct TwoPtRadial { void init(const SkPoint& center0, SkScalar rad0, const SkPoint& center1, SkScalar rad1); + // used by setup and nextT + float fRelX, fRelY, fIncX, fIncY; + float fB, fDB; + + void setup(SkScalar fx, SkScalar fy, SkScalar dfx, SkScalar dfy); + SkFixed nextT(); + static bool DontDrawT(SkFixed t) { return kDontDrawT == (uint32_t)t; } @@ -44,24 +49,11 @@ public: const SkPoint& end, SkScalar endRadius, const Descriptor&); - - virtual SkShader::Context* createContext(const SkBitmap&, const SkPaint&, const SkMatrix&, - void* storage) const SK_OVERRIDE; - virtual size_t contextSize() const SK_OVERRIDE; - - class TwoPointConicalGradientContext : public SkGradientShaderBase::GradientShaderBaseContext { - public: - TwoPointConicalGradientContext(const SkTwoPointConicalGradient& shader, - const SkBitmap& device, - const SkPaint& paint, - const SkMatrix& matrix); - ~TwoPointConicalGradientContext() {} - - virtual void shadeSpan(int x, int y, SkPMColor dstC[], int count) SK_OVERRIDE; - - private: - typedef SkGradientShaderBase::GradientShaderBaseContext INHERITED; - }; + virtual void shadeSpan(int x, int y, SkPMColor* dstCParam, + int count) SK_OVERRIDE; + virtual bool setContext(const SkBitmap& device, + const SkPaint& paint, + const SkMatrix& matrix) SK_OVERRIDE; virtual BitmapType asABitmap(SkBitmap* bitmap, SkMatrix* matrix, @@ -85,12 +77,11 @@ protected: virtual void flatten(SkWriteBuffer& buffer) const SK_OVERRIDE; private: + typedef SkGradientShaderBase INHERITED; const SkPoint fCenter1; const SkPoint fCenter2; const SkScalar fRadius1; const SkScalar fRadius2; - - typedef SkGradientShaderBase INHERITED; }; #endif diff --git a/src/effects/gradients/SkTwoPointRadialGradient.cpp b/src/effects/gradients/SkTwoPointRadialGradient.cpp index a598c6e0e3..e1359b12dd 100644 --- a/src/effects/gradients/SkTwoPointRadialGradient.cpp +++ b/src/effects/gradients/SkTwoPointRadialGradient.cpp @@ -220,60 +220,23 @@ SkShader::GradientType SkTwoPointRadialGradient::asAGradient( return kRadial2_GradientType; } -size_t SkTwoPointRadialGradient::contextSize() const { - return sizeof(TwoPointRadialGradientContext); -} - -bool SkTwoPointRadialGradient::validContext(const SkBitmap& device, const SkPaint& paint, - const SkMatrix& matrix, SkMatrix* totalInverse) const { - // For now, we might have divided by zero, so detect that. - if (0 == fDiffRadius) { - return false; - } - - return this->INHERITED::validContext(device, paint, matrix, totalInverse); -} - -SkShader::Context* SkTwoPointRadialGradient::createContext( - const SkBitmap& device, const SkPaint& paint, - const SkMatrix& matrix, void* storage) const { - if (!this->validContext(device, paint, matrix)) { - return NULL; - } - - return SkNEW_PLACEMENT_ARGS(storage, TwoPointRadialGradientContext, - (*this, device, paint, matrix)); -} - -SkTwoPointRadialGradient::TwoPointRadialGradientContext::TwoPointRadialGradientContext( - const SkTwoPointRadialGradient& shader, const SkBitmap& device, - const SkPaint& paint, const SkMatrix& matrix) - : INHERITED(shader, device, paint, matrix) -{ - // we don't have a span16 proc - fFlags &= ~kHasSpan16_Flag; -} - -void SkTwoPointRadialGradient::TwoPointRadialGradientContext::shadeSpan( - int x, int y, SkPMColor* dstCParam, int count) { +void SkTwoPointRadialGradient::shadeSpan(int x, int y, SkPMColor* dstCParam, + int count) { SkASSERT(count > 0); - const SkTwoPointRadialGradient& twoPointRadialGradient = - static_cast<const SkTwoPointRadialGradient&>(fShader); - SkPMColor* SK_RESTRICT dstC = dstCParam; // Zero difference between radii: fill with transparent black. - if (twoPointRadialGradient.fDiffRadius == 0) { + if (fDiffRadius == 0) { sk_bzero(dstC, count * sizeof(*dstC)); return; } SkMatrix::MapXYProc dstProc = fDstToIndexProc; - TileProc proc = twoPointRadialGradient.fTileProc; - const SkPMColor* SK_RESTRICT cache = fCache->getCache32(); + TileProc proc = fTileProc; + const SkPMColor* SK_RESTRICT cache = this->getCache32(); - SkScalar foura = twoPointRadialGradient.fA * 4; - bool posRoot = twoPointRadialGradient.fDiffRadius < 0; + SkScalar foura = fA * 4; + bool posRoot = fDiffRadius < 0; if (fDstToIndexClass != kPerspective_MatrixClass) { SkPoint srcPt; dstProc(fDstToIndex, SkIntToScalar(x) + SK_ScalarHalf, @@ -291,23 +254,21 @@ void SkTwoPointRadialGradient::TwoPointRadialGradientContext::shadeSpan( dx = fDstToIndex.getScaleX(); dy = fDstToIndex.getSkewY(); } - SkScalar b = (SkScalarMul(twoPointRadialGradient.fDiff.fX, fx) + - SkScalarMul(twoPointRadialGradient.fDiff.fY, fy) - - twoPointRadialGradient.fStartRadius) * 2; - SkScalar db = (SkScalarMul(twoPointRadialGradient.fDiff.fX, dx) + - SkScalarMul(twoPointRadialGradient.fDiff.fY, dy)) * 2; + SkScalar b = (SkScalarMul(fDiff.fX, fx) + + SkScalarMul(fDiff.fY, fy) - fStartRadius) * 2; + SkScalar db = (SkScalarMul(fDiff.fX, dx) + + SkScalarMul(fDiff.fY, dy)) * 2; TwoPointRadialShadeProc shadeProc = shadeSpan_twopoint_repeat; - if (SkShader::kClamp_TileMode == twoPointRadialGradient.fTileMode) { + if (SkShader::kClamp_TileMode == fTileMode) { shadeProc = shadeSpan_twopoint_clamp; - } else if (SkShader::kMirror_TileMode == twoPointRadialGradient.fTileMode) { + } else if (SkShader::kMirror_TileMode == fTileMode) { shadeProc = shadeSpan_twopoint_mirror; } else { - SkASSERT(SkShader::kRepeat_TileMode == twoPointRadialGradient.fTileMode); + SkASSERT(SkShader::kRepeat_TileMode == fTileMode); } (*shadeProc)(fx, dx, fy, dy, b, db, - twoPointRadialGradient.fSr2D2, foura, - twoPointRadialGradient.fOneOverTwoA, posRoot, + fSr2D2, foura, fOneOverTwoA, posRoot, dstC, cache, count); } else { // perspective case SkScalar dstX = SkIntToScalar(x); @@ -317,11 +278,10 @@ void SkTwoPointRadialGradient::TwoPointRadialGradientContext::shadeSpan( dstProc(fDstToIndex, dstX, dstY, &srcPt); SkScalar fx = srcPt.fX; SkScalar fy = srcPt.fY; - SkScalar b = (SkScalarMul(twoPointRadialGradient.fDiff.fX, fx) + - SkScalarMul(twoPointRadialGradient.fDiff.fY, fy) - - twoPointRadialGradient.fStartRadius) * 2; - SkFixed t = two_point_radial(b, fx, fy, twoPointRadialGradient.fSr2D2, foura, - twoPointRadialGradient.fOneOverTwoA, posRoot); + SkScalar b = (SkScalarMul(fDiff.fX, fx) + + SkScalarMul(fDiff.fY, fy) - fStartRadius) * 2; + SkFixed t = two_point_radial(b, fx, fy, fSr2D2, foura, + fOneOverTwoA, posRoot); SkFixed index = proc(t); SkASSERT(index <= 0xFFFF); *dstC++ = cache[index >> SkGradientShaderBase::kCache32Shift]; @@ -330,6 +290,23 @@ void SkTwoPointRadialGradient::TwoPointRadialGradientContext::shadeSpan( } } +bool SkTwoPointRadialGradient::setContext( const SkBitmap& device, + const SkPaint& paint, + const SkMatrix& matrix){ + // For now, we might have divided by zero, so detect that + if (0 == fDiffRadius) { + return false; + } + + if (!this->INHERITED::setContext(device, paint, matrix)) { + return false; + } + + // we don't have a span16 proc + fFlags &= ~kHasSpan16_Flag; + return true; +} + #ifndef SK_IGNORE_TO_STRING void SkTwoPointRadialGradient::toString(SkString* str) const { str->append("SkTwoPointRadialGradient: ("); diff --git a/src/effects/gradients/SkTwoPointRadialGradient.h b/src/effects/gradients/SkTwoPointRadialGradient.h index 9ba89f2920..ee1b49ee95 100644 --- a/src/effects/gradients/SkTwoPointRadialGradient.h +++ b/src/effects/gradients/SkTwoPointRadialGradient.h @@ -23,26 +23,11 @@ public: virtual GradientType asAGradient(GradientInfo* info) const SK_OVERRIDE; virtual GrEffectRef* asNewEffect(GrContext* context, const SkPaint&) const SK_OVERRIDE; - - virtual size_t contextSize() const SK_OVERRIDE; - virtual bool validContext(const SkBitmap&, const SkPaint&, - const SkMatrix&, SkMatrix* totalInverse = NULL) const SK_OVERRIDE; - virtual SkShader::Context* createContext(const SkBitmap&, const SkPaint&, const SkMatrix&, - void* storage) const SK_OVERRIDE; - - class TwoPointRadialGradientContext : public SkGradientShaderBase::GradientShaderBaseContext { - public: - TwoPointRadialGradientContext(const SkTwoPointRadialGradient& shader, - const SkBitmap& device, - const SkPaint& paint, - const SkMatrix& matrix); - ~TwoPointRadialGradientContext() {} - - virtual void shadeSpan(int x, int y, SkPMColor dstC[], int count) SK_OVERRIDE; - - private: - typedef SkGradientShaderBase::GradientShaderBaseContext INHERITED; - }; + virtual void shadeSpan(int x, int y, SkPMColor* dstCParam, + int count) SK_OVERRIDE; + virtual bool setContext(const SkBitmap& device, + const SkPaint& paint, + const SkMatrix& matrix) SK_OVERRIDE; SkScalar getCenterX1() const { return fDiff.length(); } SkScalar getStartRadius() const { return fStartRadius; } @@ -56,6 +41,7 @@ protected: virtual void flatten(SkWriteBuffer& buffer) const SK_OVERRIDE; private: + typedef SkGradientShaderBase INHERITED; const SkPoint fCenter1; const SkPoint fCenter2; const SkScalar fRadius1; @@ -64,8 +50,6 @@ private: SkScalar fStartRadius, fDiffRadius, fSr2D2, fA, fOneOverTwoA; void init(); - - typedef SkGradientShaderBase INHERITED; }; #endif |