Index: src/core/SkBlitter.cpp |
diff --git a/src/core/SkBlitter.cpp b/src/core/SkBlitter.cpp |
index f925eaa7b2d7f193ef076a7b696ef0db42c339ca..17fcdee982cdd7098e534c047b72d17585b21186 100644 |
--- a/src/core/SkBlitter.cpp |
+++ b/src/core/SkBlitter.cpp |
@@ -564,106 +564,142 @@ SkBlitter* SkBlitterClipper::apply(SkBlitter* blitter, const SkRegion* clip, |
#include "SkColorShader.h" |
#include "SkColorPriv.h" |
-class Sk3DShader : public SkShader { |
+class Sk3DShader : public SkShaderGenerator { |
public: |
Sk3DShader(SkShader* proxy) : fProxy(proxy) { |
SkSafeRef(proxy); |
- fMask = NULL; |
} |
virtual ~Sk3DShader() { |
SkSafeUnref(fProxy); |
} |
- void setMask(const SkMask* mask) { fMask = mask; } |
- |
- virtual bool setContext(const SkBitmap& device, const SkPaint& paint, |
- const SkMatrix& matrix) SK_OVERRIDE { |
- if (!this->INHERITED::setContext(device, paint, matrix)) { |
+ virtual bool validContext(const SkBitmap& device, const SkPaint& paint, |
+ const SkMatrix& matrix) const SK_OVERRIDE |
+ { |
+ if (!this->INHERITED::validateContext(device, paint, matrix)) { |
return false; |
} |
if (fProxy) { |
- 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 fProxy->validateContext(device, paint, matrix); |
} |
return true; |
} |
- virtual void endContext() SK_OVERRIDE { |
+ virtual size_t shaderImplSize() const SK_OVERRIDE { |
+ size_t size = sizeof(Sk3DShaderImpl); |
if (fProxy) { |
- fProxy->endContext(); |
+ size += fProxy->shaderImplSize(); |
} |
- this->INHERITED::endContext(); |
+ return size; |
} |
- virtual void shadeSpan(int x, int y, SkPMColor span[], int count) SK_OVERRIDE { |
+ virtual ShaderImpl* createShaderImpl(const SkBitmap& device, const SkPaint& paint, |
+ const SkMatrix& matrix, void* storage) const Sk_OVERRIDE |
+ { |
+ SkASSERT(this->validContext(device, paint, matrix)); |
+ ShaderImpl* proxyImpl; |
if (fProxy) { |
- fProxy->shadeSpan(x, y, span, count); |
+ char* proxyImplStorage = (char*) storage + sizeof(Sk3DShaderImpl); |
+ proxyImpl = fProxy->createShaderImpl(device, paint, matrix, proxyImplStorage); |
+ } else { |
+ proxyImpl = NULL; |
+ } |
+ return SkNEW_PLACEMENT_ARGS(storage, Sk3DShaderImpl, (*this, device, paint, matrix, |
+ proxyImpl)); |
+ } |
+ |
+ class Sk3DShaderImpl : public ShaderImpl { |
+ Sk3DShaderImpl(const Sk3DShader& shader, const SkBitmap& device, const SkPaint& paint, |
+ const SkMatrix& matrix, ShaderImpl* proxyImpl) |
+ : INHERITED(shader, device, paint, matrix) |
+ , fMask(NULL) |
+ , fProxyImpl(proxyImpl) |
+ { |
+ if (!fProxyImpl) { |
+ fPMColor = SkPreMultiplyColor(paint.getColor()); |
+ } |
} |
- if (fMask == NULL) { |
- if (fProxy == NULL) { |
- sk_memset32(span, fPMColor, count); |
+ virtual ~Sk3DShaderImpl() { |
+ if (fProxyImpl) { |
+ fProxyImpl->~ShaderImpl(); |
} |
- return; |
} |
- SkASSERT(fMask->fBounds.contains(x, y)); |
- SkASSERT(fMask->fBounds.contains(x + count - 1, y)); |
+ void setMask(const SkMask* mask) { fMask = mask; } |
- 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; |
+ virtual void shadeSpan(int x, int y, SkPMColor span[], int count) SK_OVERRIDE { |
+ const Sk3DShader& shader3D = static_cast<const Sk3DShader&>(fShader); |
+ if (fProxyImpl) { |
+ fProxyImpl->shadeSpan(x, y, span, count); |
+ } |
- 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); |
+ if (fMask == NULL) { |
+ if (fProxyImpl == NULL) { |
+ sk_memset32(span, fPMColor, count); |
+ } |
+ return; |
+ } |
+ 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 (fProxyImpl) { |
+ 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]; |
- 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); |
+ 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; |
} |
- } 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. |
+ ShaderImpl* fProxyImpl; |
+ SkPMColor fPMColor; |
+ }; |
#ifdef SK_DEVELOPER |
virtual void toString(SkString* str) const SK_OVERRIDE { |
@@ -685,29 +721,30 @@ public: |
protected: |
Sk3DShader(SkReadBuffer& buffer) : INHERITED(buffer) { |
fProxy = buffer.readShader(); |
- fPMColor = buffer.readColor(); |
- fMask = NULL; |
+ // Leaving this here until we bump the picture version, though this |
+ // shader should never be recorded. |
+ buffer.readColor(); |
} |
virtual void flatten(SkWriteBuffer& buffer) const SK_OVERRIDE { |
this->INHERITED::flatten(buffer); |
buffer.writeFlattenable(fProxy); |
- buffer.writeColor(fPMColor); |
+ // Leaving this here until we bump the picture version, though this |
+ // shader should never be recorded. |
+ buffer.writeColor(SkColor()); |
} |
private: |
SkShader* fProxy; |
- SkPMColor fPMColor; |
- const SkMask* fMask; |
- typedef SkShader INHERITED; |
+ typedef SkShaderGenerator INHERITED; |
}; |
class Sk3DBlitter : public SkBlitter { |
public: |
Sk3DBlitter(SkBlitter* proxy, Sk3DShader* shader) |
: fProxy(proxy) |
- , f3DShader(SkRef(shader)) |
+ , f3DShaderImpl(SkRef(shader)) |
{} |
virtual void blitH(int x, int y, int width) { |
@@ -729,22 +766,22 @@ public: |
virtual void blitMask(const SkMask& mask, const SkIRect& clip) { |
if (mask.fFormat == SkMask::k3D_Format) { |
- f3DShader->setMask(&mask); |
+ f3DShaderImpl->setMask(&mask); |
((SkMask*)&mask)->fFormat = SkMask::kA8_Format; |
fProxy->blitMask(mask, clip); |
((SkMask*)&mask)->fFormat = SkMask::k3D_Format; |
- f3DShader->setMask(NULL); |
+ f3DShaderImpl->setMask(NULL); |
} else { |
fProxy->blitMask(mask, clip); |
} |
} |
private: |
- // fProxy is unowned. It will be deleted by SkSmallAllocator. |
- SkBlitter* fProxy; |
- SkAutoTUnref<Sk3DShader> f3DShader; |
+ // Both pointers are unowned. They will be deleted by SkSmallAllocator. |
+ SkBlitter* fProxy; |
+ Sk3DShader::Sk3DShaderImpl* f3DShaderImpl; |
}; |
/////////////////////////////////////////////////////////////////////////////// |
@@ -753,9 +790,12 @@ private: |
static bool just_solid_color(const SkPaint& paint) { |
if (paint.getAlpha() == 0xFF && paint.getColorFilter() == NULL) { |
- SkShader* shader = paint.getShader(); |
- if (NULL == shader || |
- (shader->getFlags() & SkShader::kOpaqueAlpha_Flag)) { |
+ SkShaderGenerator* shader = paint.getShader(); |
+ // FIXME: This is ONLY called BEFORE setContext, when the flags are not |
+ // supposed to be meaningful. Do we need flags on the shader as well as |
+ // the impl? |
+ if (NULL == shader /*|| |
+ (shader->getFlags() & SkShader::kOpaqueAlpha_Flag)*/) { |
return true; |
} |
} |
@@ -826,7 +866,7 @@ SkBlitter* SkBlitter::Choose(const SkBitmap& device, |
return blitter; |
} |
- SkShader* shader = origPaint.getShader(); |
+ SkShaderGenerator* shader = origPaint.getShader(); |
SkColorFilter* cf = origPaint.getColorFilter(); |
SkXfermode* mode = origPaint.getXfermode(); |
Sk3DShader* shader3D = NULL; |
@@ -893,16 +933,22 @@ SkBlitter* SkBlitter::Choose(const SkBitmap& device, |
} |
/* |
- * 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. |
+ * We create a ShaderImpl object, and store it on the blitter. |
*/ |
- if (shader && !shader->setContext(device, *paint, matrix)) { |
- blitter = allocator->createT<SkNullBlitter>(); |
- return blitter; |
+ SkShaderGenerator::ShaderImpl* shaderImpl; |
+ if (shader) { |
+ if (!shader->validContext(device, *paint, matrix)) { |
+ blitter = allocator->createT<SkNullBlitter>(); |
+ return blitter; |
+ } |
+ // Now create the ShaderImpl |
+ void* storage = allocator->reserveT<SkShaderGenerator::ShaderImpl>( |
+ shader->shaderImplSize()); |
+ shaderImpl = shader->createShaderImpl(device, *paint, matrix); |
+ SkASSERT(shaderImpl); |
+ SkASSERT((void*) shaderImpl == storage); |
+ } else { |
+ shaderImpl = NULL; |
} |
@@ -913,19 +959,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); |
+ blitter = allocator->createT<SkA8_Shader_Blitter>(device, *paint, shaderImpl); |
} else { |
blitter = allocator->createT<SkA8_Blitter>(device, *paint); |
} |
break; |
case kRGB_565_SkColorType: |
- blitter = SkBlitter_ChooseD565(device, *paint, allocator); |
+ blitter = SkBlitter_ChooseD565(device, *paint, shaderImpl, allocator); |
break; |
case kPMColor_SkColorType: |
if (shader) { |
- blitter = allocator->createT<SkARGB32_Shader_Blitter>(device, *paint); |
+ blitter = allocator->createT<SkARGB32_Shader_Blitter>(device, *paint, shaderImpl); |
} else if (paint->getColor() == SK_ColorBLACK) { |
blitter = allocator->createT<SkARGB32_Black_Blitter>(device, *paint); |
} else if (paint->getAlpha() == 0xFF) { |
@@ -944,7 +990,8 @@ SkBlitter* SkBlitter::Choose(const SkBitmap& device, |
if (shader3D) { |
SkBlitter* innerBlitter = blitter; |
// innerBlitter was allocated by allocator, which will delete it. |
- blitter = allocator->createT<Sk3DBlitter>(innerBlitter, shader3D); |
+ blitter = allocator->createT<Sk3DBlitter>(innerBlitter, |
+ static_cast<Sk3DShader::Sk3DShaderImpl*>(shaderImpl); |
} |
return blitter; |
} |
@@ -956,18 +1003,13 @@ const uint32_t gMask_00FF00FF = 0xFF00FF; |
/////////////////////////////////////////////////////////////////////////////// |
-SkShaderBlitter::SkShaderBlitter(const SkBitmap& device, const SkPaint& paint) |
+SkShaderBlitter::SkShaderBlitter(const SkBitmap& device, const SkPaint& paint, |
+ SkShaderGenerator::ShaderImpl* shaderImpl) |
: INHERITED(device) { |
- fShader = paint.getShader(); |
- SkASSERT(fShader); |
- SkASSERT(fShader->setContextHasBeenCalled()); |
+ fShaderImpl = shaderImpl; |
+ SkASSERT(paint.getShader()); |
+ SkASSERT(fShaderImpl); |
- fShader->ref(); |
- fShaderFlags = fShader->getFlags(); |
+ fShaderFlags = paint.getShader()->getFlags(); |
} |
-SkShaderBlitter::~SkShaderBlitter() { |
- SkASSERT(fShader->setContextHasBeenCalled()); |
- fShader->endContext(); |
- fShader->unref(); |
-} |