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>
This commit is contained in:
parent
a2b4bdce8c
commit
030cbd5f3c
68
gm/overdrawcolorfilter.cpp
Normal file
68
gm/overdrawcolorfilter.cpp
Normal file
@ -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;)
|
@ -50,6 +50,8 @@ skia_effects_sources = [
|
|||||||
"$_src/effects/SkMergeImageFilter.cpp",
|
"$_src/effects/SkMergeImageFilter.cpp",
|
||||||
"$_src/effects/SkMorphologyImageFilter.cpp",
|
"$_src/effects/SkMorphologyImageFilter.cpp",
|
||||||
"$_src/effects/SkOffsetImageFilter.cpp",
|
"$_src/effects/SkOffsetImageFilter.cpp",
|
||||||
|
"$_src/effects/SkOverdrawColorFilter.cpp",
|
||||||
|
"$_src/effects/SkOverdrawColorFilter.h",
|
||||||
"$_src/effects/SkPackBits.cpp",
|
"$_src/effects/SkPackBits.cpp",
|
||||||
"$_src/effects/SkPackBits.h",
|
"$_src/effects/SkPackBits.h",
|
||||||
"$_src/effects/SkPaintFlagsDrawFilter.cpp",
|
"$_src/effects/SkPaintFlagsDrawFilter.cpp",
|
||||||
|
@ -198,6 +198,7 @@ gm_sources = [
|
|||||||
"$_gm/occludedrrectblur.cpp",
|
"$_gm/occludedrrectblur.cpp",
|
||||||
"$_gm/offsetimagefilter.cpp",
|
"$_gm/offsetimagefilter.cpp",
|
||||||
"$_gm/ovals.cpp",
|
"$_gm/ovals.cpp",
|
||||||
|
"$_gm/overdrawcolorfilter.cpp",
|
||||||
"$_gm/OverStroke.cpp",
|
"$_gm/OverStroke.cpp",
|
||||||
"$_gm/patch.cpp",
|
"$_gm/patch.cpp",
|
||||||
"$_gm/patchgrid.cpp",
|
"$_gm/patchgrid.cpp",
|
||||||
|
181
src/effects/SkOverdrawColorFilter.cpp
Normal file
181
src/effects/SkOverdrawColorFilter.cpp
Normal file
@ -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
|
54
src/effects/SkOverdrawColorFilter.h
Normal file
54
src/effects/SkOverdrawColorFilter.h
Normal file
@ -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
|
@ -40,6 +40,7 @@
|
|||||||
#include "SkMorphologyImageFilter.h"
|
#include "SkMorphologyImageFilter.h"
|
||||||
#include "SkNormalSource.h"
|
#include "SkNormalSource.h"
|
||||||
#include "SkOffsetImageFilter.h"
|
#include "SkOffsetImageFilter.h"
|
||||||
|
#include "../../src/effects/SkOverdrawColorFilter.h"
|
||||||
#include "SkPaintImageFilter.h"
|
#include "SkPaintImageFilter.h"
|
||||||
#include "SkPerlinNoiseShader.h"
|
#include "SkPerlinNoiseShader.h"
|
||||||
#include "SkPictureImageFilter.h"
|
#include "SkPictureImageFilter.h"
|
||||||
@ -86,6 +87,7 @@ void SkFlattenable::PrivateInitializer::InitEffects() {
|
|||||||
SkAlphaThresholdFilter::InitializeFlattenables();
|
SkAlphaThresholdFilter::InitializeFlattenables();
|
||||||
SkArithmeticMode::InitializeFlattenables();
|
SkArithmeticMode::InitializeFlattenables();
|
||||||
SkTableColorFilter::InitializeFlattenables();
|
SkTableColorFilter::InitializeFlattenables();
|
||||||
|
SkOverdrawColorFilter::InitializeFlattenables();
|
||||||
|
|
||||||
// Shader
|
// Shader
|
||||||
SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkPerlinNoiseShader)
|
SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkPerlinNoiseShader)
|
||||||
|
Loading…
Reference in New Issue
Block a user