diff options
Diffstat (limited to 'src/core')
-rw-r--r-- | src/core/SkBitmapProcShader.cpp | 118 | ||||
-rw-r--r-- | src/core/SkBitmapProcShader.h | 60 | ||||
-rw-r--r-- | src/core/SkBitmapProcState.cpp | 14 | ||||
-rw-r--r-- | src/core/SkBitmapProcState.h | 6 | ||||
-rw-r--r-- | src/core/SkBlitter.cpp | 277 | ||||
-rw-r--r-- | src/core/SkBlitter.h | 7 | ||||
-rw-r--r-- | src/core/SkBlitter_A8.cpp | 29 | ||||
-rw-r--r-- | src/core/SkBlitter_ARGB32.cpp | 76 | ||||
-rw-r--r-- | src/core/SkBlitter_RGB16.cpp | 105 | ||||
-rw-r--r-- | src/core/SkCanvas.cpp | 52 | ||||
-rw-r--r-- | src/core/SkComposeShader.cpp | 97 | ||||
-rw-r--r-- | src/core/SkCoreBlitters.h | 30 | ||||
-rw-r--r-- | src/core/SkDraw.cpp | 103 | ||||
-rw-r--r-- | src/core/SkFilterShader.cpp | 80 | ||||
-rw-r--r-- | src/core/SkFilterShader.h | 29 | ||||
-rw-r--r-- | src/core/SkPictureShader.cpp | 118 | ||||
-rw-r--r-- | src/core/SkPictureShader.h | 41 | ||||
-rw-r--r-- | src/core/SkShader.cpp | 136 | ||||
-rw-r--r-- | src/core/SkSmallAllocator.h | 23 |
19 files changed, 549 insertions, 852 deletions
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 eecfbbcc48..be87d832fd 100644 --- a/src/core/SkBitmapProcState.cpp +++ b/src/core/SkBitmapProcState.cpp @@ -360,6 +360,17 @@ bool SkBitmapProcState::lockBaseBitmap() { return true; } +void SkBitmapProcState::endContext() { + SkDELETE(fBitmapFilter); + fBitmapFilter = NULL; + fScaledBitmap.reset(); + + if (fScaledCacheID) { + SkScaledImageCache::Unlock(fScaledCacheID); + fScaledCacheID = NULL; + } +} + SkBitmapProcState::~SkBitmapProcState() { if (fScaledCacheID) { SkScaledImageCache::Unlock(fScaledCacheID); @@ -388,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; } @@ -477,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; } @@ -519,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/SkBitmapProcState.h b/src/core/SkBitmapProcState.h index 663bcb8be9..d5a354e36a 100644 --- a/src/core/SkBitmapProcState.h +++ b/src/core/SkBitmapProcState.h @@ -89,6 +89,12 @@ struct SkBitmapProcState { uint8_t fTileModeY; // CONSTRUCTOR uint8_t fFilterLevel; // chooseProcs + /** The shader will let us know when we can release some of our resources + * like scaled bitmaps. + */ + + void endContext(); + /** Platforms implement this, and can optionally overwrite only the following fields: diff --git a/src/core/SkBlitter.cpp b/src/core/SkBlitter.cpp index 7243f52161..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->~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->~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 e3451cde77..d8399717fe 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; @@ -1918,6 +1940,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()) { @@ -1933,6 +1957,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()) { @@ -1960,6 +1986,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()) { @@ -1979,6 +2007,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()) { @@ -1998,6 +2028,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()) { @@ -2028,6 +2060,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()) { @@ -2047,6 +2081,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; } @@ -2322,6 +2358,8 @@ void SkCanvas::DrawTextDecorations(const SkDraw& draw, const SkPaint& paint, void SkCanvas::onDrawText(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()) { @@ -2336,8 +2374,10 @@ void SkCanvas::onDrawText(const void* text, size_t byteLength, SkScalar x, SkSca void SkCanvas::onDrawPosText(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()) { SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint()); iter.fDevice->drawPosText(iter, text, byteLength, &pos->fX, 0, 2, @@ -2349,8 +2389,10 @@ void SkCanvas::onDrawPosText(const void* text, size_t byteLength, const SkPoint void SkCanvas::onDrawPosTextH(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()) { SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint()); iter.fDevice->drawPosText(iter, text, byteLength, xpos, constY, 1, @@ -2362,8 +2404,10 @@ void SkCanvas::onDrawPosTextH(const void* text, size_t byteLength, const SkScala void SkCanvas::onDrawTextOnPath(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()) { iter.fDevice->drawTextOnPath(iter, text, byteLength, path, matrix, looper.paint()); @@ -2395,6 +2439,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 77bc46f30a..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->~Context(); - fShaderContextB->~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 5c5e8f317c..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->~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 dc5c90b62e..bf312851ab 100644 --- a/src/core/SkPictureShader.cpp +++ b/src/core/SkPictureShader.cpp @@ -49,7 +49,7 @@ void SkPictureShader::flatten(SkWriteBuffer& buffer) const { fPicture->flatten(buffer); } -SkShader* SkPictureShader::refBitmapShader(const SkMatrix& matrix) const { +bool SkPictureShader::buildBitmapShader(const SkMatrix& matrix) const { SkASSERT(fPicture && fPicture->width() > 0 && fPicture->height() > 0); SkMatrix m; @@ -70,20 +70,17 @@ SkShader* SkPictureShader::refBitmapShader(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); @@ -91,91 +88,66 @@ SkShader* SkPictureShader::refBitmapShader(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); + + return true; } -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; +bool SkPictureShader::setContext(const SkBitmap& device, + const SkPaint& paint, + const SkMatrix& matrix) { + if (!this->buildBitmapShader(matrix)) { + return false; } - SkAutoTUnref<SkShader> bitmapShader(this->refBitmapShader(matrix)); - if (!bitmapShader || !bitmapShader->validContext(device, paint, matrix)) { - return NULL; + if (!this->INHERITED::setContext(device, paint, matrix)) { + return false; } - return bitmapShader.detach(); -} - -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 { - SkAutoTUnref<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.detach())); -} - -size_t SkPictureShader::contextSize() const { - return sizeof(PictureShaderContext); + return true; } -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->~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 @@ -196,10 +168,10 @@ void SkPictureShader::toString(SkString* str) const { #if SK_SUPPORT_GPU GrEffectRef* SkPictureShader::asNewEffect(GrContext* context, const SkPaint& paint) const { - SkAutoTUnref<SkShader> bitmapShader(this->refBitmapShader(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 d1be059182..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* refBitmapShader(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. |