diff options
author | commit-bot@chromium.org <commit-bot@chromium.org@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2013-09-06 15:31:06 +0000 |
---|---|---|
committer | commit-bot@chromium.org <commit-bot@chromium.org@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2013-09-06 15:31:06 +0000 |
commit | 91a798f121a2238639f8e2d08cc776d4f0236ceb (patch) | |
tree | 2eb3f173e69d21f3a39165f9b835643f8365e383 | |
parent | 04c500fd756053e3fe8e278a253b5ad618742d50 (diff) |
alpha threshold bitmap shader
Committed: http://code.google.com/p/skia/source/detail?r=11122
R=reed@google.com
Author: bsalomon@google.com
Review URL: https://chromiumcodereview.appspot.com/23707019
git-svn-id: http://skia.googlecode.com/svn/trunk@11131 2bbb7eff-a529-9590-31e7-b0007b416f81
-rw-r--r-- | gm/bitmapalphathreshold.cpp | 144 | ||||
-rw-r--r-- | gyp/effects.gypi | 2 | ||||
-rw-r--r-- | gyp/gmslides.gypi | 1 | ||||
-rw-r--r-- | include/core/SkShader.h | 8 | ||||
-rw-r--r-- | include/effects/SkBitmapAlphaThresholdShader.h | 24 | ||||
-rw-r--r-- | include/gpu/GrEffect.h | 5 | ||||
-rw-r--r-- | include/gpu/GrTextureAccess.h | 2 | ||||
-rw-r--r-- | src/effects/SkBitmapAlphaThresholdShader.cpp | 311 | ||||
-rw-r--r-- | src/gpu/SkGpuDevice.cpp | 5 | ||||
-rw-r--r-- | tests/GLProgramsTest.cpp | 2 |
10 files changed, 498 insertions, 6 deletions
diff --git a/gm/bitmapalphathreshold.cpp b/gm/bitmapalphathreshold.cpp new file mode 100644 index 0000000000..8af49fe351 --- /dev/null +++ b/gm/bitmapalphathreshold.cpp @@ -0,0 +1,144 @@ +/* + * Copyright 2013 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 "SkGradientShader.h" +#include "SkBitmapAlphaThresholdShader.h" +#include "SkTArray.h" +#include "SkParsePath.h" + +class BitmapAlphaThresholdGM : public skiagm::GM { +public: + BitmapAlphaThresholdGM() { + this->setBGColor(0xFF000000); + } + +private: + virtual uint32_t onGetFlags() const SK_OVERRIDE { + // narrow this flags when the shader has a CPU implementation and + // when it serializes. + return + kSkipPDF_Flag | + kSkipPicture_Flag | + kSkipPipe_Flag | + kSkipPipeCrossProcess_Flag | + kSkipTiled_Flag | + kSkip565_Flag | + kSkipScaledReplay_Flag | + kSkipPDFRasterization_Flag | + + kGPUOnly_Flag; + } + + virtual void onOnceBeforeDraw() SK_OVERRIDE { + fBM.setConfig(SkBitmap::kARGB_8888_Config, 100, 100); + if (!fBM.allocPixels()) { + return; + } + SkCanvas canvas(fBM); + SkPoint pts[] = { {0, 0}, {SkIntToScalar(fBM.width()), SkIntToScalar(fBM.height())} }; + SkColor colors[] = {0x00000000, 0xffffffff}; + SkShader* grad = SkGradientShader::CreateLinear(pts, colors, NULL, 2, + SkShader::kClamp_TileMode); + SkPaint gradPaint; + gradPaint.setShader(grad)->unref(); + gradPaint.setXfermodeMode(SkXfermode::kSrc_Mode); + canvas.drawPaint(gradPaint); + + // Construct the region used as a mask. + SkRegion bmpBoundsClip; + bmpBoundsClip.setRect(0, 0, fBM.width(), fBM.height()); + SkPath circlePath; + SkScalar radius = SkScalarSqrt(SkIntToScalar(fBM.width() * fBM.height())) / 2; + circlePath.addCircle(SkIntToScalar(fBM.width() / 2), + SkIntToScalar(fBM.height() / 2), + radius); + fMask.setPath(circlePath, bmpBoundsClip); + + SkPath batPath; + SkParsePath::FromSVGString( + "M305.214,374.779c2.463,0,3.45,0.493,3.45,0.493l1.478-6.241c0,0,1.15,4.763,1.643,9.034" + "c0.493,4.271,8.048,1.479,14.454,0.164c6.405-1.314,7.72-11.662,7.72-11.662h59.294c0,0-35.807,10.841-26.772,34.656" + "c0,0-52.889-8.048-61.101,24.967h-0.001c-8.212-33.015-61.101-24.967-61.101-24.967c9.034-23.815-26.772-34.656-26.772-34.656" + "h59.294c0,0,1.314,10.348,7.719,11.662c6.406,1.314,13.962,4.106,14.454-0.164c0.493-4.271,1.643-9.034,1.643-9.034l1.479,6.241" + "c0,0,0.985-0.493,3.449-0.493H305.214L305.214,374.779z", + &batPath); + + SkMatrix matrix; + matrix.setTranslate(-208, -280); + matrix.postScale(radius / 100, radius / 100); + batPath.transform(matrix, &batPath); + SkRegion batRegion; + batRegion.setPath(batPath, bmpBoundsClip); + + fMask.op(batRegion, SkRegion::kDifference_Op); + } + + virtual SkString onShortName() SK_OVERRIDE { + return SkString("bat"); + } + + virtual SkISize onISize() SK_OVERRIDE { + return SkISize::Make(518, 735); + } + + virtual void onDraw(SkCanvas* canvas) SK_OVERRIDE { + + SkTArray<SkMatrix> lms; + lms.push_back().reset(); + lms.push_back().setScale(SK_Scalar1 / 2, SK_Scalar1); + lms.push_back().setScale(SK_Scalar1, 2 * SK_Scalar1); + lms.push_back().setRotate(-SK_Scalar1 * 30); + lms.push_back().setSkew(0, SK_Scalar1 / 5); + + static const SkScalar kMargin = 5 * SK_Scalar1; + canvas->translate(kMargin, kMargin); + canvas->save(); + + static const U8CPU kThresholds[] = { 0x0, 0x08, 0x40, 0x80, 0xC0, 0xF0, 0xFF }; + + for (size_t i = 0; i < SK_ARRAY_COUNT(kThresholds); ++i) { + for (int j = 0; j < lms.count(); ++j) { + SkRect rect; + rect.fLeft = 0; + rect.fTop = 0; + rect.fRight = SkIntToScalar(fBM.width()); + rect.fBottom = SkIntToScalar(fBM.height()); + + SkShader* thresh; + // This SkShader currently only has a GPU implementation. + if (canvas->getDevice()->accessRenderTarget()) { + thresh = SkBitmapAlphaThresholdShader::Create(fBM, fMask, kThresholds[i]); + } else { + thresh = SkShader::CreateBitmapShader(fBM, SkShader::kClamp_TileMode, + SkShader::kClamp_TileMode); + } + + thresh->setLocalMatrix(lms[j]); + + SkPaint paint; + paint.setShader(thresh)->unref(); + + canvas->drawRect(rect, paint); + canvas->translate(SkIntToScalar(fBM.width() + kMargin), 0); + } + canvas->restore(); + canvas->translate(0, SkIntToScalar(fBM.height() + kMargin)); + canvas->save(); + } + + } + + SkBitmap fBM; + SkRegion fMask; + + typedef skiagm::GM INHERITED; +}; + +////////////////////////////////////////////////////////////////////////////// + +DEF_GM( return new BitmapAlphaThresholdGM(); ) diff --git a/gyp/effects.gypi b/gyp/effects.gypi index 56ba59f09b..9105dddfa5 100644 --- a/gyp/effects.gypi +++ b/gyp/effects.gypi @@ -12,6 +12,7 @@ '<(skia_src_path)/effects/SkArithmeticMode.cpp', '<(skia_src_path)/effects/SkAvoidXfermode.cpp', '<(skia_src_path)/effects/SkBicubicImageFilter.cpp', + '<(skia_src_path)/effects/SkBitmapAlphaThresholdShader.cpp', '<(skia_src_path)/effects/SkBitmapSource.cpp', '<(skia_src_path)/effects/SkBlurDrawLooper.cpp', '<(skia_src_path)/effects/SkBlurMask.cpp', @@ -80,6 +81,7 @@ '<(skia_include_path)/effects/SkXfermodeImageFilter.h', '<(skia_include_path)/effects/SkArithmeticMode.h', '<(skia_include_path)/effects/SkAvoidXfermode.h', + '<(skia_include_path)/effects/SkBitmapAlphaThresholdShader.h', '<(skia_include_path)/effects/SkBitmapSource.h', '<(skia_include_path)/effects/SkBlurDrawLooper.h', '<(skia_include_path)/effects/SkBlurImageFilter.h', diff --git a/gyp/gmslides.gypi b/gyp/gmslides.gypi index 52faae0448..e101baf739 100644 --- a/gyp/gmslides.gypi +++ b/gyp/gmslides.gypi @@ -10,6 +10,7 @@ '../gm/bicubicfilter.cpp', '../gm/bigmatrix.cpp', '../gm/bigtext.cpp', + '../gm/bitmapalphathreshold.cpp', '../gm/bitmapcopy.cpp', '../gm/bitmapmatrix.cpp', '../gm/bitmapfilters.cpp', diff --git a/include/core/SkShader.h b/include/core/SkShader.h index e1cab96795..2632830ef0 100644 --- a/include/core/SkShader.h +++ b/include/core/SkShader.h @@ -318,9 +318,11 @@ public: virtual GradientType asAGradient(GradientInfo* info) const; /** - * If the shader subclass has a GrEffect implementation, this installs an effect on the stage. - * The GrContext may be used by the effect to create textures. The GPU device does not call - * setContext. Instead we pass the paint here in case the shader needs paint info. + * If the shader subclass has a GrEffect implementation, this resturns the effect to install. + * The incoming color to the effect has r=g=b=a all extracted from the SkPaint's alpha. + * The output color should be the computed SkShader premul color modulated by the incoming + * color. The GrContext may be used by the effect to create textures. The GPU device does not + * call setContext. Instead we pass the SkPaint here in case the shader needs paint info. */ virtual GrEffectRef* asNewEffect(GrContext* context, const SkPaint& paint) const; diff --git a/include/effects/SkBitmapAlphaThresholdShader.h b/include/effects/SkBitmapAlphaThresholdShader.h new file mode 100644 index 0000000000..61596daff3 --- /dev/null +++ b/include/effects/SkBitmapAlphaThresholdShader.h @@ -0,0 +1,24 @@ +/* + * Copyright 2013 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "SkShader.h" +#include "SkBitmap.h" +#include "SkRegion.h" +#include "SkString.h" + +class SK_API SkBitmapAlphaThresholdShader : public SkShader { +public: + /** + * Creates a shader that samples a bitmap and a region. If the sample is inside the region + * the alpha of the bitmap color is boosted up to a threshold value. If it is + * outside the region then the bitmap alpha is decreased to the threshold value. + * The 0,0 point of the region corresponds to the upper left corner of the bitmap + * Currently, this only has a GPU implementation, doesn't respect the paint's bitmap + * filter setting, and always uses clamp mode. + */ + static SkShader* Create(const SkBitmap& bitmap, const SkRegion& region, U8CPU threshold); +}; diff --git a/include/gpu/GrEffect.h b/include/gpu/GrEffect.h index 942e580d4c..a84810c094 100644 --- a/include/gpu/GrEffect.h +++ b/include/gpu/GrEffect.h @@ -204,8 +204,9 @@ public: protected: /** * Subclasses call this from their constructor to register GrTextureAccesses. The effect - * subclass manages the lifetime of the accesses (this function only stores a pointer). This - * must only be called from the constructor because GrEffects are immutable. + * subclass manages the lifetime of the accesses (this function only stores a pointer). The + * GrTextureAccess is typically a member field of the GrEffet subclass. This must only be + * called from the constructor because GrEffects are immutable. */ void addTextureAccess(const GrTextureAccess* textureAccess); diff --git a/include/gpu/GrTextureAccess.h b/include/gpu/GrTextureAccess.h index 0f44807466..f8bb554326 100644 --- a/include/gpu/GrTextureAccess.h +++ b/include/gpu/GrTextureAccess.h @@ -18,7 +18,7 @@ class GrTexture; * Represents the filtering and tile modes used to access a texture. It is mostly used with * GrTextureAccess (defined below). Also, some of the texture cache methods require knowledge about * filtering and tiling to perform a cache lookup. If it wasn't for this latter usage this would - * be folded into GrTextureAccess. + * be folded into GrTextureAccess. The default is clamp tile modes and no filtering. */ class GrTextureParams { public: diff --git a/src/effects/SkBitmapAlphaThresholdShader.cpp b/src/effects/SkBitmapAlphaThresholdShader.cpp new file mode 100644 index 0000000000..c9275883e3 --- /dev/null +++ b/src/effects/SkBitmapAlphaThresholdShader.cpp @@ -0,0 +1,311 @@ +/* + * Copyright 2013 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "SkBitmapAlphaThresholdShader.h" + +class BATShader : public SkShader { +public: + SK_DECLARE_INST_COUNT(SkThresholdShader); + + BATShader(const SkBitmap& bitmap, SkRegion region, U8CPU); + BATShader(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) { + // We should probably do something here. + } + + + virtual void shadeSpan(int x, int y, SkPMColor[], int count) SK_OVERRIDE {}; + +#if SK_SUPPORT_GPU + virtual GrEffectRef* asNewEffect(GrContext* context, const SkPaint& paint) const SK_OVERRIDE; +#endif + + SK_DEVELOPER_TO_STRING(); + SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(BATShader) + +private: + SkBitmap fBitmap; + SkRegion fRegion; + U8CPU fThreshold; + + typedef SkShader INHERITED; +}; + +SkShader* SkBitmapAlphaThresholdShader::Create(const SkBitmap& bitmap, + const SkRegion& region, + U8CPU threshold) { + SkASSERT(threshold < 256); + return SkNEW_ARGS(BATShader, (bitmap, region, threshold)); +} + +BATShader::BATShader(const SkBitmap& bitmap, SkRegion region, U8CPU threshold) +: fBitmap(bitmap) +, fRegion(region) +, fThreshold(threshold) { +}; + + +#ifdef SK_DEVELOPER +void BATShader::toString(SkString* str) const { + str->append("BATShader: ("); + + fBitmap.toString(str); + + this->INHERITED::toString(str); + + str->append(")"); +} +#endif + +#if SK_SUPPORT_GPU +#include "GrContext.h" +#include "GrEffect.h" +#include "gl/GrGLEffect.h" +#include "gl/GrGLEffectMatrix.h" +#include "GrTBackendEffectFactory.h" +#include "GrTextureAccess.h" + +#include "SkGr.h" + +/** + * Could create specializations for some simple cases: + * - The region is empty. + * - The region fully contains the bitmap. + * - The regions is 1 rect (or maybe a small number of rects). + */ +class ThresholdEffect : public GrEffect { +public: + virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE { + return GrTBackendEffectFactory<ThresholdEffect>::getInstance(); + } + + static GrEffectRef* Create(GrTexture* bmpTexture, const SkMatrix& bmpMatrix, + GrTexture* maskTexture, const SkMatrix& maskMatrix, + U8CPU threshold) { + SkScalar thresh = SkIntToScalar(threshold) / 255; + + AutoEffectUnref effect(SkNEW_ARGS(ThresholdEffect, (bmpTexture, bmpMatrix, + maskTexture, maskMatrix, + thresh))); + return CreateEffectRef(effect); + } + + virtual void getConstantColorComponents(GrColor* color, + uint32_t* validFlags) const SK_OVERRIDE { + if ((kA_GrColorComponentFlag & *validFlags) && 0 == GrColorUnpackA(*color)) { + return; + } + *validFlags = 0; + return; + } + + static const char* Name() { return "Bitmap Alpha Threshold"; } + + class GLEffect : public GrGLEffect { + public: + GLEffect(const GrBackendEffectFactory& factory, + const GrDrawEffect& e) + : GrGLEffect(factory) + , fBmpMatrix(GrEffect::kLocal_CoordsType) + , fMaskMatrix(GrEffect::kLocal_CoordsType) + , fPrevThreshold(-SK_Scalar1) { + } + + virtual void emitCode(GrGLShaderBuilder* builder, + const GrDrawEffect& drawEffect, + EffectKey key, + const char* outputColor, + const char* inputColor, + const TextureSamplerArray& samplers) SK_OVERRIDE { + SkString bmpCoord; + SkString maskCoord; + + GrSLType bmpCoordType = fBmpMatrix.emitCode(builder, key, &bmpCoord, NULL, "Bmp"); + EffectKey maskMatrixKey = key >> GrGLEffectMatrix::kKeyBits; + GrSLType maskCoordType = fMaskMatrix.emitCode(builder, + maskMatrixKey, + &maskCoord, + NULL, + "Mask"); + + // put bitmap color in "color" + builder->fsCodeAppend("\t\tvec4 color = "); + builder->fsAppendTextureLookup(samplers[0], bmpCoord.c_str(), bmpCoordType); + builder->fsCodeAppend(";\n"); + + // put alpha from mask texture in "mask" + builder->fsCodeAppend("\t\tfloat mask = "); + builder->fsAppendTextureLookup(samplers[1], maskCoord.c_str(), maskCoordType); + builder->fsCodeAppend(".a;\n"); + + const char* threshold; + + fThresholdUniHandle = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility, + kFloat_GrSLType, + "threshold", + &threshold); + builder->fsCodeAppendf("\t\tfloat thresh = %s;\n", threshold); + + builder->fsCodeAppend("\t\tif (mask < 0.5) {\n" + "\t\t\tif (color.a > thresh) {\n" + "\t\t\t\tfloat scale = thresh / color.a;\n" + "\t\t\t\tcolor.rgb *= scale;\n" + "\t\t\t\tcolor.a = thresh;\n" + "\t\t\t}\n" + "\t\t} else if (color.a < thresh) {\n" + "\t\t\tfloat scale = thresh / color.a;\n" + "\t\t\tcolor.rgb *= scale;\n" + "\t\t\tcolor.a = thresh;\n" + "\t\t}\n"); + + builder->fsCodeAppend("color = "); + SkString outStr; + outStr.appendf("\t\t%s = ", outputColor); + GrGLSLModulatef<4>(&outStr, inputColor, "color"); + outStr.append(";\n"); + builder->fsCodeAppend(outStr.c_str()); + } + + virtual void setData(const GrGLUniformManager& uman, const GrDrawEffect& e) SK_OVERRIDE { + const ThresholdEffect& effect = e.castEffect<ThresholdEffect>(); + fBmpMatrix.setData(uman, effect.fBmpMatrix, e, effect.fBmpAccess.getTexture()); + fMaskMatrix.setData(uman, effect.fMaskMatrix, e, effect.fMaskAccess.getTexture()); + if (fPrevThreshold != effect.fThreshold) { + uman.set1f(fThresholdUniHandle, effect.fThreshold); + } + } + + static inline EffectKey GenKey(const GrDrawEffect& e, const GrGLCaps&) { + const ThresholdEffect& effect = e.castEffect<ThresholdEffect>(); + + EffectKey bmpMKey = GrGLEffectMatrix::GenKey(effect.fBmpMatrix, + e, + GrEffect::kLocal_CoordsType, + effect.fBmpAccess.getTexture()); + EffectKey maskMKey = GrGLEffectMatrix::GenKey(effect.fMaskMatrix, + e, + GrEffect::kLocal_CoordsType, + effect.fMaskAccess.getTexture()); + return bmpMKey | (maskMKey << GrGLEffectMatrix::kKeyBits); + } + + private: + GrGLEffectMatrix fBmpMatrix; + GrGLEffectMatrix fMaskMatrix; + + GrGLUniformManager::UniformHandle fThresholdUniHandle; + SkScalar fPrevThreshold; + }; + + GR_DECLARE_EFFECT_TEST; + +private: + ThresholdEffect(GrTexture* bmpTexture, const SkMatrix& bmpMatrix, + GrTexture* maskTexture, const SkMatrix& maskMatrix, + SkScalar threshold) + : fBmpAccess(bmpTexture, GrTextureParams()) + , fMaskAccess(maskTexture, GrTextureParams()) + , fBmpMatrix(bmpMatrix) + , fMaskMatrix(maskMatrix) + , fThreshold(threshold) { + this->addTextureAccess(&fBmpAccess); + this->addTextureAccess(&fMaskAccess); + } + + virtual bool onIsEqual(const GrEffect& other) const SK_OVERRIDE { + const ThresholdEffect& e = CastEffect<ThresholdEffect>(other); + return e.fBmpAccess.getTexture() == fBmpAccess.getTexture() && + e.fMaskAccess.getTexture() == fMaskAccess.getTexture() && + e.fBmpMatrix == fBmpMatrix && + e.fMaskMatrix == fMaskMatrix && + e.fThreshold == fThreshold; + } + + GrTextureAccess fBmpAccess; + GrTextureAccess fMaskAccess; + + SkMatrix fBmpMatrix; + SkMatrix fMaskMatrix; + + SkScalar fThreshold; +}; + +GR_DEFINE_EFFECT_TEST(ThresholdEffect); + +GrEffectRef* ThresholdEffect::TestCreate(SkMWCRandom* rand, + GrContext*, + const GrDrawTargetCaps&, + GrTexture* textures[]) { + GrTexture* bmpTex = textures[GrEffectUnitTest::kSkiaPMTextureIdx]; + GrTexture* maskTex = textures[GrEffectUnitTest::kAlphaTextureIdx]; + U8CPU thresh = rand->nextU() % 0xff; + return ThresholdEffect::Create(bmpTex, SkMatrix::I(), maskTex, SkMatrix::I(), thresh); +} + +GrEffectRef* BATShader::asNewEffect(GrContext* context, const SkPaint& paint) const { + SkMatrix localInverse; + if (!this->getLocalMatrix().invert(&localInverse)) { + return NULL; + } + + GrTextureDesc maskDesc; + if (context->isConfigRenderable(kAlpha_8_GrPixelConfig)) { + maskDesc.fConfig = kAlpha_8_GrPixelConfig; + } else { + maskDesc.fConfig = kRGBA_8888_GrPixelConfig; + } + maskDesc.fFlags = kRenderTarget_GrTextureFlagBit | kNoStencil_GrTextureFlagBit; + const SkIRect& bounds = fRegion.getBounds(); + // Add one pixel of border to ensure that clamp mode will be all zeros + // the outside. + maskDesc.fWidth = bounds.width() + 2; + maskDesc.fHeight = bounds.height() + 2; + GrAutoScratchTexture ast(context, maskDesc, GrContext::kApprox_ScratchTexMatch); + GrTexture* maskTexture = ast.texture(); + if (NULL == maskTexture) { + return NULL; + } + + GrPaint grPaint; + grPaint.setBlendFunc(kOne_GrBlendCoeff, kZero_GrBlendCoeff); + SkRegion::Iterator iter(fRegion); + context->setRenderTarget(maskTexture->asRenderTarget()); + context->clear(NULL, 0x0); + + // offset to ensure border is zero on top/left + SkMatrix matrix; + matrix.setTranslate(SK_Scalar1, SK_Scalar1); + context->setMatrix(matrix); + + while (!iter.done()) { + SkRect rect = SkRect::MakeFromIRect(iter.rect()); + context->drawRect(grPaint, rect); + iter.next(); + } + + GrTexture* bmpTexture = GrLockAndRefCachedBitmapTexture(context, fBitmap, NULL); + if (NULL == bmpTexture) { + return NULL; + } + + SkMatrix bmpMatrix = localInverse; + bmpMatrix.postIDiv(bmpTexture->width(), bmpTexture->height()); + + SkMatrix maskMatrix = localInverse; + // compensate for the border + maskMatrix.postTranslate(SK_Scalar1, SK_Scalar1); + maskMatrix.postIDiv(maskTexture->width(), maskTexture->height()); + + GrEffectRef* effect = ThresholdEffect::Create(bmpTexture, bmpMatrix, + maskTexture, maskMatrix, + fThreshold); + + GrUnlockAndUnrefCachedBitmapTexture(bmpTexture); + + return effect; +} + +#endif diff --git a/src/gpu/SkGpuDevice.cpp b/src/gpu/SkGpuDevice.cpp index 571b8a0a7d..ea8a06e632 100644 --- a/src/gpu/SkGpuDevice.cpp +++ b/src/gpu/SkGpuDevice.cpp @@ -535,6 +535,11 @@ inline bool skPaint2GrPaintShader(SkGpuDevice* dev, return skPaint2GrPaintNoShader(dev, skPaint, false, constantColor, grPaint); } + // SkShader::asNewEffect() may do offscreen rendering. Setup default drawing state + // Also require shader to set the render target . + GrContext::AutoWideOpenIdentityDraw awo(dev->context(), NULL); + GrContext::AutoRenderTarget(dev->context(), NULL); + // setup the shader as the first color effect on the paint SkAutoTUnref<GrEffectRef> effect(shader->asNewEffect(dev->context(), skPaint)); if (NULL != effect.get()) { diff --git a/tests/GLProgramsTest.cpp b/tests/GLProgramsTest.cpp index c9f69f0ef3..316465840e 100644 --- a/tests/GLProgramsTest.cpp +++ b/tests/GLProgramsTest.cpp @@ -228,6 +228,7 @@ DEFINE_GPUTESTCLASS("GLPrograms", GLProgramsTestClass, GLProgramsTest) #include "SkLightingImageFilter.h" #include "SkMagnifierImageFilter.h" #include "SkColorMatrixFilter.h" +#include "SkBitmapAlphaThresholdShader.h" void forceLinking(); @@ -240,6 +241,7 @@ void forceLinking() { SkMatrix::I()); SkScalar matrix[20]; SkColorMatrixFilter cmf(matrix); + SkBitmapAlphaThresholdShader::Create(SkBitmap(), SkRegion(), 0x80); } #endif |