Chromium Code Reviews| Index: src/effects/SkValidateImageFilter.cpp |
| diff --git a/src/effects/SkValidateImageFilter.cpp b/src/effects/SkValidateImageFilter.cpp |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..7576227f36a5f7d6217d16f7688189c7965833c0 |
| --- /dev/null |
| +++ b/src/effects/SkValidateImageFilter.cpp |
| @@ -0,0 +1,263 @@ |
| +/* |
| + * Copyright 2013 Google Inc. |
|
Stephen White
2014/03/25 17:10:14
Nit: 2014.
|
| + * |
| + * Use of this source code is governed by a BSD-style license that can be |
| + * found in the LICENSE file. |
| + */ |
| + |
| +#include "SkValidateImageFilter.h" |
| +#include "SkReadBuffer.h" |
| +#include "SkWriteBuffer.h" |
| +#include "SkColorPriv.h" |
| +#if SK_SUPPORT_GPU |
| +#include "GrContext.h" |
| +#include "GrCoordTransform.h" |
| +#include "gl/GrGLEffect.h" |
| +#include "GrTBackendEffectFactory.h" |
| +#endif |
| + |
| +namespace { |
| + |
| +void validatePMColor(const SkBitmap* src, SkBitmap* dst, const SkIRect& bounds) { |
|
Stephen White
2014/03/25 17:10:14
Nit: "src" should be a const ref, according to ski
|
| + for (int y = bounds.top(); y < bounds.bottom(); ++y) { |
| + const SkPMColor* srcPtr = src->getAddr32(bounds.left(), y); |
| + SkPMColor* dstPtr = dst->getAddr32(bounds.left(), y); |
| + for (int x = bounds.left(); x < bounds.right(); ++x, ++srcPtr) { |
| + SkPMColor srcColor = *srcPtr; |
| + unsigned a = SkGetPackedA32(srcColor); |
| + unsigned r = SkGetPackedR32(srcColor); |
| + unsigned g = SkGetPackedG32(srcColor); |
| + unsigned b = SkGetPackedB32(srcColor); |
| + *dstPtr++ = SkPackARGB32(a, SkTMin(r, a), SkTMin(g, a), SkTMin(b, a)); |
| + } |
| + } |
| +} |
| + |
| +} // end namespace |
| + |
| +/////////////////////////////////////////////////////////////////////////////// |
| + |
| +SkValidateImageFilter::SkValidateImageFilter(SkImageFilter* input) |
| + : INHERITED(input) |
| +{ |
| +} |
| + |
| +SkValidateImageFilter::~SkValidateImageFilter() { |
| +} |
| + |
| +SkValidateImageFilter::SkValidateImageFilter(SkReadBuffer& buffer) |
| + : INHERITED(1, buffer) |
| +{ |
| +} |
| + |
| +void SkValidateImageFilter::flatten(SkWriteBuffer& buffer) const { |
| + this->INHERITED::flatten(buffer); |
| +} |
| + |
| +bool SkValidateImageFilter::onFilterImage(Proxy* proxy, |
| + const SkBitmap& src, |
| + const Context& ctx, |
| + SkBitmap* dst, |
| + SkIPoint* offset) const { |
| + SkBitmap source = src; |
| + SkImageFilter* input = getInput(0); |
| + SkIPoint sourceOffset = SkIPoint::Make(0, 0); |
| + if ((!input || !input->filterImage(proxy, src, ctx, &source, &sourceOffset))) { |
| + return false; |
| + } |
| + |
| + SkIRect bounds; |
| + if (!this->applyCropRect(ctx, source, sourceOffset, &bounds)) { |
| + return false; |
| + } |
| + |
| + SkAutoLockPixels alp(source); |
| + if (!source.getPixels()) { |
| + return false; |
| + } |
| + |
| + dst->setConfig(src.config(), bounds.width(), bounds.height()); |
| + dst->allocPixels(); |
| + if (!dst->getPixels()) { |
| + return false; |
| + } |
| + |
| + // Make sure none of the RGB components are larger than A |
| + validatePMColor(&source, dst, bounds); |
| + |
| + offset->fX = bounds.left(); |
| + offset->fY = bounds.top(); |
| + return true; |
| +} |
| + |
| +/////////////////////////////////////////////////////////////////////////////// |
| + |
| +#if SK_SUPPORT_GPU |
| +class GrGLValidateEffect : public GrGLEffect { |
| +public: |
| + GrGLValidateEffect(const GrBackendEffectFactory& factory, |
| + const GrDrawEffect& drawEffect); |
| + virtual ~GrGLValidateEffect(); |
| + |
| + virtual void emitCode(GrGLShaderBuilder*, |
| + const GrDrawEffect&, |
| + EffectKey, |
| + const char* outputColor, |
| + const char* inputColor, |
| + const TransformedCoordsArray&, |
| + const TextureSamplerArray&) SK_OVERRIDE; |
| + |
| + static inline EffectKey GenKey(const GrDrawEffect&, const GrGLCaps&); |
| + |
| +private: |
| + typedef GrGLEffect INHERITED; |
| +}; |
| + |
| +/////////////////////////////////////////////////////////////////////////////// |
| + |
| +class GrValidateEffect : public GrEffect { |
| +public: |
| + static GrEffectRef* Create(GrTexture* color) { |
|
Stephen White
2014/03/25 17:10:14
Same here.
|
| + AutoEffectUnref effect(SkNEW_ARGS(GrValidateEffect, (color))); |
| + return CreateEffectRef(effect); |
| + } |
| + |
| + virtual ~GrValidateEffect(); |
| + |
| + virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE; |
| + |
| + typedef GrGLValidateEffect GLEffect; |
| + static const char* Name() { return "Validate"; } |
| + |
| + virtual void getConstantColorComponents(GrColor* color, uint32_t* validFlags) const SK_OVERRIDE; |
| + |
| +private: |
| + virtual bool onIsEqual(const GrEffect&) const SK_OVERRIDE; |
| + |
| + GrValidateEffect(GrTexture* color); |
| + |
| + GR_DECLARE_EFFECT_TEST; |
| + |
| + GrCoordTransform fColorTransform; |
| + GrTextureAccess fColorAccess; |
| + |
| + typedef GrEffect INHERITED; |
| +}; |
| + |
| +bool SkValidateImageFilter::filterImageGPU(Proxy* proxy, const SkBitmap& src, const Context& ctx, |
| + SkBitmap* result, SkIPoint* offset) const { |
| + SkBitmap source = src; |
| + SkImageFilter* input = getInput(0); |
| + SkIPoint sourceOffset = SkIPoint::Make(0, 0); |
| + if (!input || !input->getInputResultGPU(proxy, src, ctx, &source, &sourceOffset)) { |
| + return false; |
| + } |
| + |
| + SkIRect bounds; |
| + if (!this->applyCropRect(ctx, source, sourceOffset, &bounds)) { |
| + return false; |
| + } |
| + |
| + GrTexture* color = source.getTexture(); |
|
Stephen White
2014/03/25 17:10:14
Nit: maybe call this sourceTexture instead.
|
| + GrContext* context = color->getContext(); |
| + |
| + GrTextureDesc desc; |
| + desc.fFlags = kRenderTarget_GrTextureFlagBit | kNoStencil_GrTextureFlagBit; |
| + desc.fWidth = bounds.width(); |
| + desc.fHeight = bounds.height(); |
| + desc.fConfig = kSkia8888_GrPixelConfig; |
| + |
| + GrAutoScratchTexture ast(context, desc); |
| + SkAutoTUnref<GrTexture> dst(ast.detach()); |
| + |
| + GrContext::AutoRenderTarget art(context, dst->asRenderTarget()); |
| + |
| + GrPaint paint; |
| + paint.addColorEffect(GrValidateEffect::Create(color))->unref(); |
| + |
| + SkIRect colorBounds = bounds; |
| + colorBounds.offset(-sourceOffset); |
| + GrContext::AutoMatrix am; |
| + am.setIdentity(context); |
| + SkMatrix matrix; |
| + matrix.setTranslate(-SkIntToScalar(colorBounds.x()), |
| + -SkIntToScalar(colorBounds.y())); |
| + context->concatMatrix(matrix); |
| + context->drawRect(paint, SkRect::Make(colorBounds)); |
| + offset->fX = bounds.left(); |
| + offset->fY = bounds.top(); |
| + WrapTexture(dst, bounds.width(), bounds.height(), result); |
| + return true; |
| +} |
| + |
| +/////////////////////////////////////////////////////////////////////////////// |
| + |
| +GrValidateEffect::GrValidateEffect(GrTexture* color) |
| + : fColorTransform(kLocal_GrCoordSet, color), |
| + fColorAccess(color) { |
| + this->addCoordTransform(&fColorTransform); |
| + this->addTextureAccess(&fColorAccess); |
| +} |
| + |
| +GrValidateEffect::~GrValidateEffect() { |
| +} |
| + |
| +bool GrValidateEffect::onIsEqual(const GrEffect&) const { |
| + return true; |
| +} |
| + |
| +const GrBackendEffectFactory& GrValidateEffect::getFactory() const { |
| + return GrTBackendEffectFactory<GrValidateEffect>::getInstance(); |
| +} |
| + |
| +void GrValidateEffect::getConstantColorComponents(GrColor* color, uint32_t* validFlags) const { |
| + *validFlags = 0; |
| +} |
| + |
| +/////////////////////////////////////////////////////////////////////////////// |
| + |
| +GR_DEFINE_EFFECT_TEST(GrValidateEffect); |
| + |
| +GrEffectRef* GrValidateEffect::TestCreate(SkRandom* random, |
| + GrContext*, |
| + const GrDrawTargetCaps&, |
| + GrTexture* textures[]) { |
| + int texIdx = random->nextBool() ? GrEffectUnitTest::kSkiaPMTextureIdx : |
| + GrEffectUnitTest::kAlphaTextureIdx; |
| + return GrValidateEffect::Create(textures[texIdx]); |
| +} |
| + |
| +/////////////////////////////////////////////////////////////////////////////// |
| + |
| +GrGLValidateEffect::GrGLValidateEffect(const GrBackendEffectFactory& factory, |
| + const GrDrawEffect& drawEffect) |
| + : INHERITED(factory) { |
| +} |
| + |
| +GrGLValidateEffect::~GrGLValidateEffect() { |
| +} |
| + |
| +void GrGLValidateEffect::emitCode(GrGLShaderBuilder* builder, |
| + const GrDrawEffect&, |
| + EffectKey key, |
| + const char* outputColor, |
| + const char* inputColor, |
| + const TransformedCoordsArray& coords, |
| + const TextureSamplerArray& samplers) { |
| + const char* color = "col"; |
| + |
| + // Get input color |
| + builder->fsCodeAppendf("\t\tvec4 %s = ", color); |
| + builder->fsAppendTextureLookup(samplers[0], coords[0].c_str(), coords[0].type()); |
| + builder->fsCodeAppend(";\n"); |
| + |
| + // Make sure none of the RGB components are larger than A |
| + builder->fsCodeAppendf("%s = vec4(min(%s.rgb, %s.a), %s.a);\n", |
| + outputColor, color, color, color); |
| +} |
| + |
| +GrGLEffect::EffectKey GrGLValidateEffect::GenKey(const GrDrawEffect& drawEffect, |
| + const GrGLCaps&) { |
| + return 0; |
| +} |
| +#endif |