aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar Matt Sarett <msarett@google.com>2016-11-22 15:48:50 -0500
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2016-11-22 21:27:42 +0000
commit030cbd5f3cc60255b887fb88920fb655c8a2a9be (patch)
tree5e1d050baec746da7f2fd2a83a128ab4e9d9cd1b
parenta2b4bdce8cfd1a91407595a25683ecff982af22e (diff)
Add SkOverdrawColorFilter
Uses the value in the src alpha channel to choose how to set the dst pixel. This is a part of a multi-part change to detect and display gpu overdraw on Android. CQ_INCLUDE_TRYBOTS=master.client.skia.compile:Build-Ubuntu-GCC-x86_64-Debug-NoGPU-Trybot BUG:32370375 GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=5113 Change-Id: I07040929d8a46bbadd499dccec75eebef0e11d11 Reviewed-on: https://skia-review.googlesource.com/5113 Commit-Queue: Matt Sarett <msarett@google.com> Reviewed-by: Brian Salomon <bsalomon@google.com>
-rw-r--r--gm/overdrawcolorfilter.cpp68
-rw-r--r--gn/effects.gni2
-rw-r--r--gn/gm.gni1
-rw-r--r--src/effects/SkOverdrawColorFilter.cpp181
-rw-r--r--src/effects/SkOverdrawColorFilter.h54
-rw-r--r--src/ports/SkGlobalInitialization_default.cpp2
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",
diff --git a/gn/gm.gni b/gn/gm.gni
index 7e70c89931..4732e0368d 100644
--- a/gn/gm.gni
+++ b/gn/gm.gni
@@ -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)