diff options
-rw-r--r-- | gm/overdrawcolorfilter.cpp | 68 | ||||
-rw-r--r-- | gn/effects.gni | 2 | ||||
-rw-r--r-- | gn/gm.gni | 1 | ||||
-rw-r--r-- | src/effects/SkOverdrawColorFilter.cpp | 181 | ||||
-rw-r--r-- | src/effects/SkOverdrawColorFilter.h | 54 | ||||
-rw-r--r-- | src/ports/SkGlobalInitialization_default.cpp | 2 |
6 files changed, 308 insertions, 0 deletions
diff --git a/gm/overdrawcolorfilter.cpp b/gm/overdrawcolorfilter.cpp new file mode 100644 index 0000000000..2eba228045 --- /dev/null +++ b/gm/overdrawcolorfilter.cpp @@ -0,0 +1,68 @@ +/* + * Copyright 2016 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 "SkCanvas.h" +#include "SkOverdrawColorFilter.h" + +static inline void set_bitmap(SkBitmap* bitmap, uint8_t alpha) { + for (int y = 0; y < bitmap->height(); y++) { + for (int x = 0; x < bitmap->width(); x++) { + uint8_t* addr = bitmap->getAddr8(x, y); + *addr = alpha; + } + } + + bitmap->notifyPixelsChanged(); +} + +class OverdrawColorFilter : public skiagm::GM { +public: + OverdrawColorFilter() {} + +protected: + virtual SkString onShortName() override { + return SkString("overdrawcolorfilter");; + } + + virtual SkISize onISize() override { + return SkISize::Make(200, 400); + } + + void onDraw(SkCanvas* canvas) override { + static const SkPMColor colors[SkOverdrawColorFilter::kNumColors] = { + 0x80800000, 0x80008000, 0x80000080, 0x80808000, 0x80008080, 0x80800080, + }; + + SkPaint paint; + sk_sp<SkColorFilter> colorFilter = SkOverdrawColorFilter::Make(colors); + paint.setColorFilter(colorFilter); + + SkImageInfo info = SkImageInfo::MakeA8(100, 100); + SkBitmap bitmap; + bitmap.allocPixels(info); + set_bitmap(&bitmap, 0); + canvas->drawBitmap(bitmap, 0, 0, &paint); + set_bitmap(&bitmap, 1); + canvas->drawBitmap(bitmap, 0, 100, &paint); + set_bitmap(&bitmap, 2); + canvas->drawBitmap(bitmap, 0, 200, &paint); + set_bitmap(&bitmap, 3); + canvas->drawBitmap(bitmap, 0, 300, &paint); + set_bitmap(&bitmap, 4); + canvas->drawBitmap(bitmap, 100, 0, &paint); + set_bitmap(&bitmap, 5); + canvas->drawBitmap(bitmap, 100, 100, &paint); + set_bitmap(&bitmap, 6); + canvas->drawBitmap(bitmap, 100, 200, &paint); + } + +private: + typedef GM INHERITED; +}; + +DEF_GM(return new OverdrawColorFilter;) diff --git a/gn/effects.gni b/gn/effects.gni index 97e0f98654..3bb84aceba 100644 --- a/gn/effects.gni +++ b/gn/effects.gni @@ -50,6 +50,8 @@ skia_effects_sources = [ "$_src/effects/SkMergeImageFilter.cpp", "$_src/effects/SkMorphologyImageFilter.cpp", "$_src/effects/SkOffsetImageFilter.cpp", + "$_src/effects/SkOverdrawColorFilter.cpp", + "$_src/effects/SkOverdrawColorFilter.h", "$_src/effects/SkPackBits.cpp", "$_src/effects/SkPackBits.h", "$_src/effects/SkPaintFlagsDrawFilter.cpp", @@ -198,6 +198,7 @@ gm_sources = [ "$_gm/occludedrrectblur.cpp", "$_gm/offsetimagefilter.cpp", "$_gm/ovals.cpp", + "$_gm/overdrawcolorfilter.cpp", "$_gm/OverStroke.cpp", "$_gm/patch.cpp", "$_gm/patchgrid.cpp", diff --git a/src/effects/SkOverdrawColorFilter.cpp b/src/effects/SkOverdrawColorFilter.cpp new file mode 100644 index 0000000000..c3bcd0e616 --- /dev/null +++ b/src/effects/SkOverdrawColorFilter.cpp @@ -0,0 +1,181 @@ +/* + * Copyright 2016 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "SkOverdrawColorFilter.h" + +void SkOverdrawColorFilter::filterSpan(const SkPMColor src[], int count, SkPMColor dst[]) const { + for (int x = 0; x < count; x++) { + uint8_t alpha = SkGetPackedA32(src[x]); + if (alpha >= kNumColors) { + alpha = kNumColors - 1; + } + + dst[x] = fColors[alpha]; + } +} + +void SkOverdrawColorFilter::toString(SkString* str) const { + str->append("SkOverdrawColorFilter ("); + for (int i = 0; i < kNumColors; i++) { + str->appendf("%d: %x\n", i, fColors[i]); + } + str->append(")"); +} + +void SkOverdrawColorFilter::flatten(SkWriteBuffer& buffer) const { + buffer.writeByteArray(fColors, kNumColors * sizeof(SkPMColor)); +} + +sk_sp<SkFlattenable> SkOverdrawColorFilter::CreateProc(SkReadBuffer& buffer) { + SkPMColor colors[kNumColors]; + size_t size = buffer.getArrayCount(); + if (!buffer.validate(size == sizeof(colors))) { + return nullptr; + } + if (!buffer.readByteArray(colors, sizeof(colors))) { + return nullptr; + } + + return SkOverdrawColorFilter::Make(colors); +} + +SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkOverdrawColorFilter) + SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkOverdrawColorFilter) +SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END + +#if SK_SUPPORT_GPU + +#include "GrFragmentProcessor.h" +#include "GrInvariantOutput.h" +#include "glsl/GrGLSLFragmentProcessor.h" +#include "glsl/GrGLSLFragmentShaderBuilder.h" + +class OverdrawFragmentProcessor : public GrFragmentProcessor { +public: + static sk_sp<GrFragmentProcessor> Make(const SkPMColor* colors); + + const char* name() const override { return "Overdraw"; } + +private: + GrGLSLFragmentProcessor* onCreateGLSLInstance() const override; + void onGetGLSLProcessorKey(const GrGLSLCaps&, GrProcessorKeyBuilder*) const override {} + bool onIsEqual(const GrFragmentProcessor&) const override; + void onComputeInvariantOutput(GrInvariantOutput* inout) const override; + + OverdrawFragmentProcessor(const GrColor4f* colors); + + GrColor4f fColors[SkOverdrawColorFilter::kNumColors]; + + typedef GrFragmentProcessor INHERITED; +}; + +class GLOverdrawFragmentProcessor : public GrGLSLFragmentProcessor { +public: + GLOverdrawFragmentProcessor(const GrColor4f* colors); + + void emitCode(EmitArgs&) override; + +protected: + void onSetData(const GrGLSLProgramDataManager&, const GrProcessor&) override {} + +private: + GrColor4f fColors[SkOverdrawColorFilter::kNumColors]; + + typedef GrGLSLFragmentProcessor INHERITED; +}; + +sk_sp<GrFragmentProcessor> SkOverdrawColorFilter::asFragmentProcessor(GrContext*, + SkColorSpace*) const { + return OverdrawFragmentProcessor::Make(fColors); +} + +sk_sp<GrFragmentProcessor> OverdrawFragmentProcessor::Make(const SkPMColor* colors) { + GrColor4f grColors[SkOverdrawColorFilter::kNumColors]; + for (int i = 0; i < SkOverdrawColorFilter::kNumColors; i++) { + grColors[i] = GrColor4f::FromGrColor(GrColorPackRGBA(SkGetPackedR32(colors[i]), + SkGetPackedG32(colors[i]), + SkGetPackedB32(colors[i]), + SkGetPackedA32(colors[i]))); + } + + return sk_sp<OverdrawFragmentProcessor>(new OverdrawFragmentProcessor(grColors)); +} + +OverdrawFragmentProcessor::OverdrawFragmentProcessor(const GrColor4f* colors) { + this->initClassID<OverdrawFragmentProcessor>(); + memcpy(fColors, colors, SkOverdrawColorFilter::kNumColors * sizeof(GrColor4f)); +} + +GrGLSLFragmentProcessor* OverdrawFragmentProcessor::onCreateGLSLInstance() const { + return new GLOverdrawFragmentProcessor(fColors); +} + +bool OverdrawFragmentProcessor::onIsEqual(const GrFragmentProcessor& other) const { + const OverdrawFragmentProcessor& that = other.cast<OverdrawFragmentProcessor>(); + return 0 == memcmp(fColors, that.fColors, + sizeof(GrColor4f) * SkOverdrawColorFilter::kNumColors); +} + +void OverdrawFragmentProcessor::onComputeInvariantOutput(GrInvariantOutput* inout) const { + inout->invalidateComponents(kRGBA_GrColorComponentFlags, GrInvariantOutput::kWill_ReadInput); +} + +GLOverdrawFragmentProcessor::GLOverdrawFragmentProcessor(const GrColor4f* colors) { + memcpy(fColors, colors, SkOverdrawColorFilter::kNumColors * sizeof(GrColor4f)); +} + +void GLOverdrawFragmentProcessor::emitCode(EmitArgs& args) { + GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder; + if (nullptr == args.fInputColor) { + fragBuilder->codeAppendf("%s.rgba = vec4(%f, %f, %f, %f);", args.fOutputColor, + fColors[5].fRGBA[0], + fColors[5].fRGBA[1], + fColors[5].fRGBA[2], + fColors[5].fRGBA[3]); + } else { + fragBuilder->codeAppendf("float alpha = 255.0 * %s.a;", args.fInputColor); + fragBuilder->codeAppendf("if (alpha < 0.5) {"); + fragBuilder->codeAppendf(" %s.rgba = vec4(%f, %f, %f, %f);", args.fOutputColor, + fColors[0].fRGBA[0], + fColors[0].fRGBA[1], + fColors[0].fRGBA[2], + fColors[0].fRGBA[3]); + fragBuilder->codeAppendf("} else if (alpha < 1.5) {"); + fragBuilder->codeAppendf(" %s.rgba = vec4(%f, %f, %f, %f);", args.fOutputColor, + fColors[1].fRGBA[0], + fColors[1].fRGBA[1], + fColors[1].fRGBA[2], + fColors[1].fRGBA[3]); + fragBuilder->codeAppendf("} else if (alpha < 2.5) {"); + fragBuilder->codeAppendf(" %s.rgba = vec4(%f, %f, %f, %f);", args.fOutputColor, + fColors[2].fRGBA[0], + fColors[2].fRGBA[1], + fColors[2].fRGBA[2], + fColors[2].fRGBA[3]); + fragBuilder->codeAppendf("} else if (alpha < 3.5) {"); + fragBuilder->codeAppendf(" %s.rgba = vec4(%f, %f, %f, %f);", args.fOutputColor, + fColors[3].fRGBA[0], + fColors[3].fRGBA[1], + fColors[3].fRGBA[2], + fColors[3].fRGBA[3]); + fragBuilder->codeAppendf("} else if (alpha < 4.5) {"); + fragBuilder->codeAppendf(" %s.rgba = vec4(%f, %f, %f, %f);", args.fOutputColor, + fColors[4].fRGBA[0], + fColors[4].fRGBA[1], + fColors[4].fRGBA[2], + fColors[4].fRGBA[3]); + fragBuilder->codeAppendf("} else {"); + fragBuilder->codeAppendf(" %s.rgba = vec4(%f, %f, %f, %f);", args.fOutputColor, + fColors[5].fRGBA[0], + fColors[5].fRGBA[1], + fColors[5].fRGBA[2], + fColors[5].fRGBA[3]); + fragBuilder->codeAppendf("}"); + } +} + +#endif diff --git a/src/effects/SkOverdrawColorFilter.h b/src/effects/SkOverdrawColorFilter.h new file mode 100644 index 0000000000..6c5ce592f3 --- /dev/null +++ b/src/effects/SkOverdrawColorFilter.h @@ -0,0 +1,54 @@ +/* + * Copyright 2016 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "SkColorFilter.h" +#include "../../src/core/SkReadBuffer.h" + +#ifndef SkOverdrawColorFilter_DEFINED +#define SkOverdrawColorFilter_DEFINED + +/** + * Uses the value in the src alpha channel to set the dst pixel. + * 0 -> fColors[0] + * 1 -> fColors[1] + * ... + * 5 (or larger) -> fColors[5] + * + */ +class SkOverdrawColorFilter : public SkColorFilter { +public: + static constexpr int kNumColors = 6; + + static sk_sp<SkOverdrawColorFilter> Make(const SkPMColor colors[kNumColors]) { + return sk_sp<SkOverdrawColorFilter>(new SkOverdrawColorFilter(colors)); + } + +#if SK_SUPPORT_GPU + sk_sp<GrFragmentProcessor> asFragmentProcessor(GrContext*, SkColorSpace*) const override; +#endif + + void filterSpan(const SkPMColor src[], int count, SkPMColor dst[]) const override; + void toString(SkString* str) const override; + + static sk_sp<SkFlattenable> CreateProc(SkReadBuffer& buffer); + Factory getFactory() const override { return CreateProc; } + SK_DECLARE_FLATTENABLE_REGISTRAR_GROUP() + +protected: + void flatten(SkWriteBuffer& buffer) const override; + +private: + SkOverdrawColorFilter(const SkPMColor colors[kNumColors]) { + memcpy(fColors, colors, kNumColors * sizeof(SkPMColor)); + } + + SkPMColor fColors[kNumColors]; + + typedef SkColorFilter INHERITED; +}; + +#endif // SkOverdrawColorFilter_DEFINED diff --git a/src/ports/SkGlobalInitialization_default.cpp b/src/ports/SkGlobalInitialization_default.cpp index 750da4af41..6b9dcacdef 100644 --- a/src/ports/SkGlobalInitialization_default.cpp +++ b/src/ports/SkGlobalInitialization_default.cpp @@ -40,6 +40,7 @@ #include "SkMorphologyImageFilter.h" #include "SkNormalSource.h" #include "SkOffsetImageFilter.h" +#include "../../src/effects/SkOverdrawColorFilter.h" #include "SkPaintImageFilter.h" #include "SkPerlinNoiseShader.h" #include "SkPictureImageFilter.h" @@ -86,6 +87,7 @@ void SkFlattenable::PrivateInitializer::InitEffects() { SkAlphaThresholdFilter::InitializeFlattenables(); SkArithmeticMode::InitializeFlattenables(); SkTableColorFilter::InitializeFlattenables(); + SkOverdrawColorFilter::InitializeFlattenables(); // Shader SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkPerlinNoiseShader) |