| 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();
|
| -}
|
|
|