aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/core
diff options
context:
space:
mode:
Diffstat (limited to 'src/core')
-rw-r--r--src/core/SkBitmapProcShader.cpp118
-rw-r--r--src/core/SkBitmapProcShader.h60
-rw-r--r--src/core/SkBitmapProcState.cpp14
-rw-r--r--src/core/SkBitmapProcState.h6
-rw-r--r--src/core/SkBlitter.cpp277
-rw-r--r--src/core/SkBlitter.h7
-rw-r--r--src/core/SkBlitter_A8.cpp29
-rw-r--r--src/core/SkBlitter_ARGB32.cpp76
-rw-r--r--src/core/SkBlitter_RGB16.cpp105
-rw-r--r--src/core/SkCanvas.cpp52
-rw-r--r--src/core/SkComposeShader.cpp97
-rw-r--r--src/core/SkCoreBlitters.h30
-rw-r--r--src/core/SkDraw.cpp103
-rw-r--r--src/core/SkFilterShader.cpp80
-rw-r--r--src/core/SkFilterShader.h29
-rw-r--r--src/core/SkPictureShader.cpp118
-rw-r--r--src/core/SkPictureShader.h41
-rw-r--r--src/core/SkShader.cpp136
-rw-r--r--src/core/SkSmallAllocator.h23
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.