From 9f23a27ed9961fd4575864e590eda328452895e7 Mon Sep 17 00:00:00 2001 From: reed Date: Wed, 10 Sep 2014 10:20:24 -0700 Subject: make set3DMask virtual, so we can safely notify the shadercontext also boost preallocated storage to account for this combo of bitmapshader + emboss + colorfilter BUG=skia: R=djsollen@google.com Author: reed@google.com Review URL: https://codereview.chromium.org/563563002 bug:16307475 Change-Id: I404fa776511a27b7be1b3b41dcb06b8b828a4716 --- gm/emboss.cpp | 61 +++++++++++++++++++++++++++++++++++++++++++ gyp/gmslides.gypi | 1 + include/core/SkShader.h | 3 +++ src/core/SkBitmapProcShader.h | 2 +- src/core/SkBlitter.cpp | 20 +++++++------- src/core/SkFilterShader.h | 5 ++++ 6 files changed, 81 insertions(+), 11 deletions(-) create mode 100644 gm/emboss.cpp diff --git a/gm/emboss.cpp b/gm/emboss.cpp new file mode 100644 index 0000000000..c2ee49723f --- /dev/null +++ b/gm/emboss.cpp @@ -0,0 +1,61 @@ +/* + * Copyright 2014 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "gm.h" +#include "SkBlurMaskFilter.h" +#include "SkCanvas.h" +#include "SkColorFilter.h" + +#include "SkColorFilter.h" +static SkBitmap make_bm() { + SkBitmap bm; + bm.allocN32Pixels(100, 100); + + SkCanvas canvas(bm); + canvas.clear(0); + SkPaint paint; + paint.setAntiAlias(true); + canvas.drawCircle(50, 50, 50, paint); + return bm; +} + +class EmbossGM : public skiagm::GM { +public: + EmbossGM() { + } + +protected: + virtual SkString onShortName() SK_OVERRIDE { + return SkString("emboss"); + } + + virtual SkISize onISize() SK_OVERRIDE { + return SkISize::Make(600, 120); + } + + virtual void onDraw(SkCanvas* canvas) SK_OVERRIDE { + SkPaint paint; + SkBitmap bm = make_bm(); + canvas->drawBitmap(bm, 10, 10, &paint); + + const SkScalar dir[] = { 1, 1, 1 }; + paint.setMaskFilter(SkBlurMaskFilter::CreateEmboss(3, dir, 0.3f, 0.1f))->unref(); + canvas->translate(bm.width() + SkIntToScalar(10), 0); + canvas->drawBitmap(bm, 10, 10, &paint); + + // this combination of emboss+colorfilter used to crash -- so we exercise it to + // confirm that we have a fix. + paint.setColorFilter(SkColorFilter::CreateModeFilter(0xFFFF0000, SkXfermode::kSrcATop_Mode))->unref(); + canvas->translate(bm.width() + SkIntToScalar(10), 0); + canvas->drawBitmap(bm, 10, 10, &paint); + } + +private: + typedef skiagm::GM INHERITED; +}; + +DEF_GM( return SkNEW(EmbossGM); ) diff --git a/gyp/gmslides.gypi b/gyp/gmslides.gypi index 18e589b3f4..ae3279f4b8 100644 --- a/gyp/gmslides.gypi +++ b/gyp/gmslides.gypi @@ -70,6 +70,7 @@ '../gm/drrect.cpp', '../gm/etc1bitmap.cpp', '../gm/extractbitmap.cpp', + '../gm/emboss.cpp', '../gm/emptypath.cpp', '../gm/fatpathfill.cpp', '../gm/factory.cpp', diff --git a/include/core/SkShader.h b/include/core/SkShader.h index 5ec23ca94f..0b7a702cb1 100644 --- a/include/core/SkShader.h +++ b/include/core/SkShader.h @@ -192,6 +192,9 @@ public: return SkShader::CanCallShadeSpan16(this->getFlags()); } + // Notification from blitter::blitMask in case we need to see the non-alpha channels + virtual void set3DMask(const SkMask*) {} + protected: // Reference to shader, so we don't have to dupe information. const SkShader& fShader; diff --git a/src/core/SkBitmapProcShader.h b/src/core/SkBitmapProcShader.h index 08e8397a73..c12b548a5f 100644 --- a/src/core/SkBitmapProcShader.h +++ b/src/core/SkBitmapProcShader.h @@ -71,7 +71,7 @@ private: // 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, 768> SkTBlitterAllocator; +typedef SkSmallAllocator<3, 1024> 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/SkBlitter.cpp b/src/core/SkBlitter.cpp index cb84ec7d9d..2560ee968c 100644 --- a/src/core/SkBlitter.cpp +++ b/src/core/SkBlitter.cpp @@ -620,7 +620,7 @@ public: } } - void setMask(const SkMask* mask) { fMask = mask; } + virtual void set3DMask(const SkMask* mask) SK_OVERRIDE { fMask = mask; } virtual void shadeSpan(int x, int y, SkPMColor span[], int count) SK_OVERRIDE { if (fProxyContext) { @@ -737,9 +737,9 @@ private: class Sk3DBlitter : public SkBlitter { public: - Sk3DBlitter(SkBlitter* proxy, Sk3DShader::Sk3DShaderContext* shaderContext) + Sk3DBlitter(SkBlitter* proxy, SkShader::Context* shaderContext) : fProxy(proxy) - , f3DShaderContext(shaderContext) + , fShaderContext(shaderContext) {} virtual void blitH(int x, int y, int width) { @@ -761,13 +761,13 @@ public: virtual void blitMask(const SkMask& mask, const SkIRect& clip) { if (mask.fFormat == SkMask::k3D_Format) { - f3DShaderContext->setMask(&mask); + fShaderContext->set3DMask(&mask); ((SkMask*)&mask)->fFormat = SkMask::kA8_Format; fProxy->blitMask(mask, clip); ((SkMask*)&mask)->fFormat = SkMask::k3D_Format; - f3DShaderContext->setMask(NULL); + fShaderContext->set3DMask(NULL); } else { fProxy->blitMask(mask, clip); } @@ -775,8 +775,8 @@ public: private: // Both pointers are unowned. They will be deleted by SkSmallAllocator. - SkBlitter* fProxy; - Sk3DShader::Sk3DShaderContext* f3DShaderContext; + SkBlitter* fProxy; + SkShader::Context* fShaderContext; }; /////////////////////////////////////////////////////////////////////////////// @@ -984,9 +984,9 @@ 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(innerBlitter, - static_cast(shaderContext)); + // We know shaderContext or its proxies is of type Sk3DShaderContext, so we need to + // wrapper the blitter to notify it when we see an emboss mask. + blitter = allocator->createT(innerBlitter, shaderContext); } return blitter; } diff --git a/src/core/SkFilterShader.h b/src/core/SkFilterShader.h index 1a4b71fe46..9c74a8c3af 100644 --- a/src/core/SkFilterShader.h +++ b/src/core/SkFilterShader.h @@ -30,6 +30,11 @@ public: 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; + virtual void set3DMask(const SkMask* mask) SK_OVERRIDE { + // forward to our proxy + fShaderContext->set3DMask(mask); + } + private: SkShader::Context* fShaderContext; -- cgit v1.2.3