| Index: src/core/SkBlitter.cpp
|
| diff --git a/src/core/SkBlitter.cpp b/src/core/SkBlitter.cpp
|
| index ad518742712704ee8365ba5ae6e57aa11a032c36..52a05eded8fda41b55cc66a300875877b90e3f00 100644
|
| --- a/src/core/SkBlitter.cpp
|
| +++ b/src/core/SkBlitter.cpp
|
| @@ -26,15 +26,6 @@
|
|
|
| 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 @@
|
| 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);
|
| + 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)) {
|
| + return false;
|
| + }
|
| if (fProxy) {
|
| - size += fProxy->contextSize();
|
| - }
|
| - return size;
|
| - }
|
| -
|
| - 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)) {
|
| - return false;
|
| - }
|
| + 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 void endContext() SK_OVERRIDE {
|
| if (fProxy) {
|
| - return fProxy->validContext(device, paint, matrix);
|
| - }
|
| - 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;
|
| + fProxy->endContext();
|
| + }
|
| + this->INHERITED::endContext();
|
| + }
|
| +
|
| + virtual void shadeSpan(int x, int y, SkPMColor span[], int count) SK_OVERRIDE {
|
| if (fProxy) {
|
| - char* proxyContextStorage = (char*) storage + sizeof(Sk3DShaderContext);
|
| - proxyContext = fProxy->createContext(device, paint, matrix, proxyContextStorage);
|
| - SkASSERT(proxyContext);
|
| - } else {
|
| - proxyContext = NULL;
|
| - }
|
| - return SkNEW_PLACEMENT_ARGS(storage, Sk3DShaderContext, (*this, device, paint, matrix,
|
| - proxyContext));
|
| - }
|
| -
|
| - 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 ~Sk3DShaderContext() {
|
| - if (fProxyContext) {
|
| - fProxyContext->SkShader::Context::~Context();
|
| - }
|
| - }
|
| -
|
| - void setMask(const SkMask* mask) { fMask = mask; }
|
| -
|
| - virtual void shadeSpan(int x, int y, SkPMColor span[], int count) SK_OVERRIDE {
|
| - if (fProxyContext) {
|
| - fProxyContext->shadeSpan(x, y, span, count);
|
| - }
|
| -
|
| - if (fMask == NULL) {
|
| - if (fProxyContext == 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 (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]) {
|
| + fProxy->shadeSpan(x, y, span, count);
|
| + }
|
| +
|
| + if (fMask == NULL) {
|
| + if (fProxy == 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 (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);
|
| +
|
| 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;
|
| }
|
| }
|
| - }
|
| -
|
| - private:
|
| - // Unowned.
|
| - const SkMask* fMask;
|
| - // Memory is unowned, but we need to call the destructor.
|
| - SkShader::Context* fProxyContext;
|
| - SkPMColor fPMColor;
|
| -
|
| - typedef SkShader::Context INHERITED;
|
| - };
|
| + } 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;
|
| + }
|
| + }
|
| + }
|
| + }
|
|
|
| #ifndef SK_IGNORE_TO_STRING
|
| virtual void toString(SkString* str) const SK_OVERRIDE {
|
| @@ -741,30 +685,29 @@
|
| 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 @@
|
|
|
| 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 @@
|
| 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 @@
|
| }
|
|
|
| /*
|
| - * 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 @@
|
| 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 @@
|
| 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 @@
|
|
|
| ///////////////////////////////////////////////////////////////////////////////
|
|
|
| -SkShaderBlitter::SkShaderBlitter(const SkBitmap& device, const SkPaint& paint,
|
| - SkShader::Context* shaderContext)
|
| - : INHERITED(device)
|
| - , fShader(paint.getShader())
|
| - , fShaderContext(shaderContext) {
|
| +SkShaderBlitter::SkShaderBlitter(const SkBitmap& device, const SkPaint& paint)
|
| + : INHERITED(device) {
|
| + fShader = paint.getShader();
|
| SkASSERT(fShader);
|
| - SkASSERT(fShaderContext);
|
| + SkASSERT(fShader->setContextHasBeenCalled());
|
|
|
| fShader->ref();
|
| - fShaderFlags = fShaderContext->getFlags();
|
| + fShaderFlags = fShader->getFlags();
|
| }
|
|
|
| SkShaderBlitter::~SkShaderBlitter() {
|
| + SkASSERT(fShader->setContextHasBeenCalled());
|
| + fShader->endContext();
|
| fShader->unref();
|
| }
|
| -
|
| -bool SkShaderBlitter::resetShaderContext(const SkBitmap& device, const SkPaint& paint,
|
| - const SkMatrix& matrix) {
|
| - if (!fShader->validContext(device, paint, matrix)) {
|
| - return false;
|
| - }
|
| -
|
| - // Only destroy the old context if we have a new one. We need to ensure to have a
|
| - // live context in fShaderContext because the storage is owned by an SkSmallAllocator
|
| - // outside of this class.
|
| - // The new context will be of the same size as the old one because we use the same
|
| - // shader to create it. It is therefore safe to re-use the storage.
|
| - fShaderContext->SkShader::Context::~Context();
|
| - fShaderContext = fShader->createContext(device, paint, matrix, (void*)fShaderContext);
|
| - SkASSERT(fShaderContext);
|
| -
|
| - return true;
|
| -}
|
|
|