| OLD | NEW |
| (Empty) |
| 1 /* | |
| 2 * Copyright 2013 Google Inc. | |
| 3 * | |
| 4 * Use of this source code is governed by a BSD-style license that can be | |
| 5 * found in the LICENSE file. | |
| 6 */ | |
| 7 | |
| 8 #include "SkBitmapAlphaThresholdShader.h" | |
| 9 | |
| 10 class BATShader : public SkShader { | |
| 11 public: | |
| 12 SK_DECLARE_INST_COUNT(BATShader); | |
| 13 | |
| 14 BATShader(const SkBitmap& bitmap, SkRegion region, U8CPU); | |
| 15 BATShader(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) { | |
| 16 // We should probably do something here. | |
| 17 } | |
| 18 | |
| 19 | |
| 20 virtual void shadeSpan(int x, int y, SkPMColor[], int count) SK_OVERRIDE {}; | |
| 21 | |
| 22 #if SK_SUPPORT_GPU | |
| 23 virtual GrEffectRef* asNewEffect(GrContext* context, const SkPaint& paint) c
onst SK_OVERRIDE; | |
| 24 #endif | |
| 25 | |
| 26 SK_DEVELOPER_TO_STRING(); | |
| 27 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(BATShader) | |
| 28 | |
| 29 private: | |
| 30 SkBitmap fBitmap; | |
| 31 SkRegion fRegion; | |
| 32 U8CPU fThreshold; | |
| 33 | |
| 34 typedef SkShader INHERITED; | |
| 35 }; | |
| 36 | |
| 37 SkShader* SkBitmapAlphaThresholdShader::Create(const SkBitmap& bitmap, | |
| 38 const SkRegion& region, | |
| 39 U8CPU threshold) { | |
| 40 SkASSERT(threshold < 256); | |
| 41 return SkNEW_ARGS(BATShader, (bitmap, region, threshold)); | |
| 42 } | |
| 43 | |
| 44 BATShader::BATShader(const SkBitmap& bitmap, SkRegion region, U8CPU threshold) | |
| 45 : fBitmap(bitmap) | |
| 46 , fRegion(region) | |
| 47 , fThreshold(threshold) { | |
| 48 }; | |
| 49 | |
| 50 | |
| 51 #ifdef SK_DEVELOPER | |
| 52 void BATShader::toString(SkString* str) const { | |
| 53 str->append("BATShader: ("); | |
| 54 | |
| 55 fBitmap.toString(str); | |
| 56 | |
| 57 this->INHERITED::toString(str); | |
| 58 | |
| 59 str->append(")"); | |
| 60 } | |
| 61 #endif | |
| 62 | |
| 63 #if SK_SUPPORT_GPU | |
| 64 #include "GrContext.h" | |
| 65 #include "GrCoordTransform.h" | |
| 66 #include "GrEffect.h" | |
| 67 #include "gl/GrGLEffect.h" | |
| 68 #include "GrTBackendEffectFactory.h" | |
| 69 #include "GrTextureAccess.h" | |
| 70 | |
| 71 #include "SkGr.h" | |
| 72 | |
| 73 /** | |
| 74 * Could create specializations for some simple cases: | |
| 75 * - The region is empty. | |
| 76 * - The region fully contains the bitmap. | |
| 77 * - The regions is 1 rect (or maybe a small number of rects). | |
| 78 */ | |
| 79 class ThresholdEffect : public GrEffect { | |
| 80 public: | |
| 81 virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE { | |
| 82 return GrTBackendEffectFactory<ThresholdEffect>::getInstance(); | |
| 83 } | |
| 84 | |
| 85 static GrEffectRef* Create(GrTexture* bmpTexture, const SkMatrix& bmpMatrix, | |
| 86 GrTexture* maskTexture, const SkMatrix& maskMatri
x, | |
| 87 U8CPU threshold) { | |
| 88 SkScalar thresh = SkIntToScalar(threshold) / 255; | |
| 89 | |
| 90 AutoEffectUnref effect(SkNEW_ARGS(ThresholdEffect, (bmpTexture, bmpMatri
x, | |
| 91 maskTexture, maskMat
rix, | |
| 92 thresh))); | |
| 93 return CreateEffectRef(effect); | |
| 94 } | |
| 95 | |
| 96 virtual void getConstantColorComponents(GrColor* color, | |
| 97 uint32_t* validFlags) const SK_OVERR
IDE { | |
| 98 if ((kA_GrColorComponentFlag & *validFlags) && 0 == GrColorUnpackA(*colo
r)) { | |
| 99 return; | |
| 100 } | |
| 101 *validFlags = 0; | |
| 102 return; | |
| 103 } | |
| 104 | |
| 105 static const char* Name() { return "Bitmap Alpha Threshold"; } | |
| 106 | |
| 107 class GLEffect : public GrGLEffect { | |
| 108 public: | |
| 109 GLEffect(const GrBackendEffectFactory& factory, | |
| 110 const GrDrawEffect& e) | |
| 111 : GrGLEffect(factory) | |
| 112 , fPrevThreshold(-SK_Scalar1) { | |
| 113 } | |
| 114 | |
| 115 virtual void emitCode(GrGLShaderBuilder* builder, | |
| 116 const GrDrawEffect& drawEffect, | |
| 117 EffectKey key, | |
| 118 const char* outputColor, | |
| 119 const char* inputColor, | |
| 120 const TransformedCoordsArray& coords, | |
| 121 const TextureSamplerArray& samplers) SK_OVERRIDE { | |
| 122 // put bitmap color in "color" | |
| 123 builder->fsCodeAppend("\t\tvec4 color = "); | |
| 124 builder->fsAppendTextureLookup(samplers[0], coords[0].c_str(), coord
s[0].type()); | |
| 125 builder->fsCodeAppend(";\n"); | |
| 126 | |
| 127 // put alpha from mask texture in "mask" | |
| 128 builder->fsCodeAppend("\t\tfloat mask = "); | |
| 129 builder->fsAppendTextureLookup(samplers[1], coords[1].c_str(), coord
s[1].type()); | |
| 130 builder->fsCodeAppend(".a;\n"); | |
| 131 | |
| 132 const char* threshold; | |
| 133 | |
| 134 fThresholdUniHandle = builder->addUniform(GrGLShaderBuilder::kFragme
nt_Visibility, | |
| 135 kFloat_GrSLType, | |
| 136 "threshold", | |
| 137 &threshold); | |
| 138 builder->fsCodeAppendf("\t\tfloat thresh = %s;\n", threshold); | |
| 139 | |
| 140 builder->fsCodeAppend("\t\tif (mask < 0.5) {\n" | |
| 141 "\t\t\tif (color.a > thresh) {\n" | |
| 142 "\t\t\t\tfloat scale = thresh / color.a;\n" | |
| 143 "\t\t\t\tcolor.rgb *= scale;\n" | |
| 144 "\t\t\t\tcolor.a = thresh;\n" | |
| 145 "\t\t\t}\n" | |
| 146 "\t\t} else if (color.a < thresh) {\n" | |
| 147 "\t\t\tfloat scale = thresh / color.a;\n" | |
| 148 "\t\t\tcolor.rgb *= scale;\n" | |
| 149 "\t\t\tcolor.a = thresh;\n" | |
| 150 "\t\t}\n"); | |
| 151 | |
| 152 builder->fsCodeAppendf("color = %s = %s;\n", outputColor, | |
| 153 (GrGLSLExpr4(inputColor) * GrGLSLExpr4("color
")).c_str()); | |
| 154 } | |
| 155 | |
| 156 virtual void setData(const GrGLUniformManager& uman, const GrDrawEffect&
e) SK_OVERRIDE { | |
| 157 const ThresholdEffect& effect = e.castEffect<ThresholdEffect>(); | |
| 158 if (fPrevThreshold != effect.fThreshold) { | |
| 159 uman.set1f(fThresholdUniHandle, effect.fThreshold); | |
| 160 } | |
| 161 } | |
| 162 | |
| 163 private: | |
| 164 GrGLUniformManager::UniformHandle fThresholdUniHandle; | |
| 165 SkScalar fPrevThreshold; | |
| 166 }; | |
| 167 | |
| 168 GR_DECLARE_EFFECT_TEST; | |
| 169 | |
| 170 private: | |
| 171 ThresholdEffect(GrTexture* bmpTexture, const SkMatrix& bmpMatrix, | |
| 172 GrTexture* maskTexture, const SkMatrix& maskMatrix, | |
| 173 SkScalar threshold) | |
| 174 : fBmpTransform(kLocal_GrCoordSet, bmpMatrix, bmpTexture) | |
| 175 , fBmpAccess(bmpTexture, GrTextureParams()) | |
| 176 , fMaskTransform(kLocal_GrCoordSet, maskMatrix, maskTexture) | |
| 177 , fMaskAccess(maskTexture, GrTextureParams()) | |
| 178 , fThreshold(threshold) { | |
| 179 this->addCoordTransform(&fBmpTransform); | |
| 180 this->addTextureAccess(&fBmpAccess); | |
| 181 this->addCoordTransform(&fMaskTransform); | |
| 182 this->addTextureAccess(&fMaskAccess); | |
| 183 } | |
| 184 | |
| 185 virtual bool onIsEqual(const GrEffect& other) const SK_OVERRIDE { | |
| 186 const ThresholdEffect& e = CastEffect<ThresholdEffect>(other); | |
| 187 return e.fBmpAccess.getTexture() == fBmpAccess.getTexture() && | |
| 188 e.fMaskAccess.getTexture() == fMaskAccess.getTexture() && | |
| 189 e.fBmpTransform.getMatrix() == fBmpTransform.getMatrix() && | |
| 190 e.fMaskTransform.getMatrix() == fMaskTransform.getMatrix() && | |
| 191 e.fThreshold == fThreshold; | |
| 192 } | |
| 193 | |
| 194 GrCoordTransform fBmpTransform; | |
| 195 GrTextureAccess fBmpAccess; | |
| 196 GrCoordTransform fMaskTransform; | |
| 197 GrTextureAccess fMaskAccess; | |
| 198 | |
| 199 SkScalar fThreshold; | |
| 200 }; | |
| 201 | |
| 202 GR_DEFINE_EFFECT_TEST(ThresholdEffect); | |
| 203 | |
| 204 GrEffectRef* ThresholdEffect::TestCreate(SkRandom* rand, | |
| 205 GrContext*, | |
| 206 const GrDrawTargetCaps&, | |
| 207 GrTexture* textures[]) { | |
| 208 GrTexture* bmpTex = textures[GrEffectUnitTest::kSkiaPMTextureIdx]; | |
| 209 GrTexture* maskTex = textures[GrEffectUnitTest::kAlphaTextureIdx]; | |
| 210 U8CPU thresh = rand->nextU() % 0xff; | |
| 211 return ThresholdEffect::Create(bmpTex, SkMatrix::I(), maskTex, SkMatrix::I()
, thresh); | |
| 212 } | |
| 213 | |
| 214 GrEffectRef* BATShader::asNewEffect(GrContext* context, const SkPaint& paint) co
nst { | |
| 215 SkMatrix localInverse; | |
| 216 if (!this->getLocalMatrix().invert(&localInverse)) { | |
| 217 return NULL; | |
| 218 } | |
| 219 | |
| 220 GrTextureDesc maskDesc; | |
| 221 if (context->isConfigRenderable(kAlpha_8_GrPixelConfig, false)) { | |
| 222 maskDesc.fConfig = kAlpha_8_GrPixelConfig; | |
| 223 } else { | |
| 224 maskDesc.fConfig = kRGBA_8888_GrPixelConfig; | |
| 225 } | |
| 226 maskDesc.fFlags = kRenderTarget_GrTextureFlagBit | kNoStencil_GrTextureFlagB
it; | |
| 227 const SkIRect& bounds = fRegion.getBounds(); | |
| 228 // Add one pixel of border to ensure that clamp mode will be all zeros | |
| 229 // the outside. | |
| 230 maskDesc.fWidth = bounds.width() + 2; | |
| 231 maskDesc.fHeight = bounds.height() + 2; | |
| 232 GrAutoScratchTexture ast(context, maskDesc, GrContext::kApprox_ScratchTexMat
ch); | |
| 233 GrTexture* maskTexture = ast.texture(); | |
| 234 if (NULL == maskTexture) { | |
| 235 return NULL; | |
| 236 } | |
| 237 | |
| 238 GrPaint grPaint; | |
| 239 grPaint.setBlendFunc(kOne_GrBlendCoeff, kZero_GrBlendCoeff); | |
| 240 SkRegion::Iterator iter(fRegion); | |
| 241 context->setRenderTarget(maskTexture->asRenderTarget()); | |
| 242 context->clear(NULL, 0x0, true); | |
| 243 | |
| 244 // offset to ensure border is zero on top/left | |
| 245 SkMatrix matrix; | |
| 246 matrix.setTranslate(SK_Scalar1, SK_Scalar1); | |
| 247 context->setMatrix(matrix); | |
| 248 | |
| 249 while (!iter.done()) { | |
| 250 SkRect rect = SkRect::Make(iter.rect()); | |
| 251 context->drawRect(grPaint, rect); | |
| 252 iter.next(); | |
| 253 } | |
| 254 | |
| 255 GrTexture* bmpTexture = GrLockAndRefCachedBitmapTexture(context, fBitmap, NU
LL); | |
| 256 if (NULL == bmpTexture) { | |
| 257 return NULL; | |
| 258 } | |
| 259 | |
| 260 SkMatrix bmpMatrix = localInverse; | |
| 261 bmpMatrix.postIDiv(bmpTexture->width(), bmpTexture->height()); | |
| 262 | |
| 263 SkMatrix maskMatrix = localInverse; | |
| 264 // compensate for the border | |
| 265 maskMatrix.postTranslate(SK_Scalar1, SK_Scalar1); | |
| 266 maskMatrix.postIDiv(maskTexture->width(), maskTexture->height()); | |
| 267 | |
| 268 GrEffectRef* effect = ThresholdEffect::Create(bmpTexture, bmpMatrix, | |
| 269 maskTexture, maskMatrix, | |
| 270 fThreshold); | |
| 271 | |
| 272 GrUnlockAndUnrefCachedBitmapTexture(bmpTexture); | |
| 273 | |
| 274 return effect; | |
| 275 } | |
| 276 | |
| 277 #endif | |
| OLD | NEW |