hide drawlooper from paint

Bug: skia: 4783

Change-Id: I1d0ad1683a2e8345d8ea13db9b69b568ada827dc
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/228573
Reviewed-by: Florin Malita <fmalita@chromium.org>
Commit-Queue: Mike Reed <reed@google.com>
This commit is contained in:
Mike Reed 2019-07-22 10:06:32 -04:00 committed by Skia Commit-Bot
parent b115d5de65
commit 766b42b7ba
24 changed files with 127 additions and 13 deletions

View File

@ -18,6 +18,8 @@
#include "include/effects/SkLayerDrawLooper.h"
#include "src/core/SkBlurMask.h"
#ifdef SK_SUPPORT_LEGACY_DRAWLOOPER
// Large blurred RR appear frequently on web pages. This benchmark measures our
// performance in this case.
class BlurRoundRectBench : public Benchmark {
@ -85,3 +87,5 @@ DEF_BENCH(return new BlurRoundRectBench(100, 100, 6);)
// Other radii options
DEF_BENCH(return new BlurRoundRectBench(100, 100, 30);)
DEF_BENCH(return new BlurRoundRectBench(100, 100, 90);)
#endif

View File

@ -13,6 +13,8 @@
#include "include/effects/SkLayerDrawLooper.h"
#include "include/utils/SkRandom.h"
#ifdef SK_SUPPORT_LEGACY_DRAWLOOPER
// This bench replicates a problematic use case of a draw looper used
// to create an inner blurred rect
class RectoriBench : public Benchmark {
@ -100,3 +102,5 @@ private:
};
DEF_BENCH(return new RectoriBench();)
#endif

View File

@ -4,6 +4,7 @@
// HASH=84ec12a36e50df5ac565cc7a75ffbe9f
REG_FIDDLE(Draw_Looper_Methods, 256, 128, false, 0) {
void draw(SkCanvas* canvas) {
#ifdef SK_SUPPORT_LEGACY_DRAWLOOPER
SkLayerDrawLooper::LayerInfo info;
info.fPaintBits = (SkLayerDrawLooper::BitFlags) SkLayerDrawLooper::kColorFilter_Bit;
info.fColorMode = SkBlendMode::kSrc;
@ -16,5 +17,6 @@ void draw(SkCanvas* canvas) {
SkPaint paint;
paint.setDrawLooper(looperBuilder.detach());
canvas->drawCircle(50, 50, 50, paint);
#endif
}
} // END FIDDLE

View File

@ -4,10 +4,12 @@
// HASH=af4c5acc7a91e7f23c2af48018903ad4
REG_FIDDLE(Paint_getDrawLooper, 256, 256, true, 0) {
void draw(SkCanvas* canvas) {
#ifdef SK_SUPPORT_LEGACY_DRAWLOOPER
SkPaint paint;
SkDebugf("nullptr %c= draw looper\n", paint.getDrawLooper() ? '!' : '=');
SkLayerDrawLooper::Builder looperBuilder;
paint.setDrawLooper(looperBuilder.detach());
SkDebugf("nullptr %c= draw looper\n", paint.getDrawLooper() ? '!' : '=');
#endif
}
} // END FIDDLE

View File

@ -4,11 +4,13 @@
// HASH=2a3782c33f04ed17a725d0e449c6f7c3
REG_FIDDLE(Paint_refDrawLooper, 256, 256, true, 0) {
void draw(SkCanvas* canvas) {
#ifdef SK_SUPPORT_LEGACY_DRAWLOOPER
SkPaint paint1, paint2;
SkLayerDrawLooper::Builder looperBuilder;
paint1.setDrawLooper(looperBuilder.detach());
SkDebugf("draw looper unique: %s\n", paint1.getDrawLooper()->unique() ? "true" : "false");
paint2.setDrawLooper(paint1.refDrawLooper());
SkDebugf("draw looper unique: %s\n", paint1.getDrawLooper()->unique() ? "true" : "false");
#endif
}
} // END FIDDLE

View File

@ -4,6 +4,7 @@
// HASH=bf10f838b330f0a3a3266d42ea68a638
REG_FIDDLE(Paint_setDrawLooper, 256, 128, false, 0) {
void draw(SkCanvas* canvas) {
#ifdef SK_SUPPORT_LEGACY_DRAWLOOPER
SkPaint paint;
paint.setDrawLooper(SkBlurDrawLooper::Make(0x7FFF0000, 4, -5, -10));
paint.setStyle(SkPaint::kStroke_Style);
@ -11,5 +12,6 @@ void draw(SkCanvas* canvas) {
paint.setAntiAlias(true);
paint.setColor(0x7f0000ff);
canvas->drawCircle(70, 70, 50, paint);
#endif
}
} // END FIDDLE

View File

@ -29,6 +29,7 @@
#include "include/effects/SkLayerDrawLooper.h"
#include "src/core/SkBlurMask.h"
#ifdef SK_SUPPORT_LEGACY_DRAWLOOPER
// This GM mimics a blurred RR seen in the wild.
class BlurRoundRectGM : public skiagm::GM {
public:
@ -92,6 +93,10 @@ private:
typedef skiagm::GM INHERITED;
};
// Rounded rect with two opposite corners with large radii, the other two
// small.
DEF_GM(return new BlurRoundRectGM(100, 100);)
#endif
/*
* Spits out a dummy gradient to test blur with shader on paint
@ -179,8 +184,4 @@ private:
// ran wrong number of tests')
//DEF_GM(return new BlurRoundRectGM(600, 5514, 6);)
// Rounded rect with two opposite corners with large radii, the other two
// small.
DEF_GM(return new BlurRoundRectGM(100, 100);)
DEF_GM(return new SimpleBlurRoundRectGM();)

View File

@ -82,6 +82,7 @@ protected:
fPaints.push_back(p);
}
#ifdef SK_SUPPORT_LEGACY_DRAWLOOPER
{
// AA with blur
SkPaint p;
@ -91,7 +92,7 @@ protected:
SkIntToScalar(5), SkIntToScalar(10)));
fPaints.push_back(p);
}
#endif
{
// AA with stroke style
SkPaint p;

View File

@ -25,6 +25,8 @@
#include "src/core/SkBlurMask.h"
#include "tools/ToolUtils.h"
#ifdef SK_SUPPORT_LEGACY_DRAWLOOPER
#define WIDTH 200
#define HEIGHT 200
@ -102,3 +104,5 @@ private:
//////////////////////////////////////////////////////////////////////////////
DEF_GM( return new DrawLooperGM; )
#endif

View File

@ -24,6 +24,8 @@
#include "src/core/SkBlurMask.h"
#include "src/core/SkClipOpPriv.h"
#ifdef SK_SUPPORT_LEGACY_DRAWLOOPER
namespace {
// This GM tests 3 different ways of drawing four shadows around a square:
@ -255,3 +257,5 @@ const SkColor MegaLooperGM::gColors[4] = {
DEF_GM( return new MegaLooperGM(MegaLooperGM::k0x0_Type); )
DEF_GM( return new MegaLooperGM(MegaLooperGM::k4x1_Type); )
DEF_GM( return new MegaLooperGM(MegaLooperGM::k1x4_Type); )
#endif

View File

@ -97,6 +97,7 @@ protected:
fPaints.push_back(p);
}
#ifdef SK_SUPPORT_LEGACY_DRAWLOOPER
{
// AA with blur
SkPaint p;
@ -107,7 +108,7 @@ protected:
SkIntToScalar(5), SkIntToScalar(10)));
fPaints.push_back(p);
}
#endif
{
// AA with stroke style
SkPaint p;

View File

@ -24,6 +24,8 @@
#include "include/effects/SkBlurDrawLooper.h"
#include "src/core/SkBlurMask.h"
#ifdef SK_SUPPORT_LEGACY_DRAWLOOPER
namespace skiagm {
///////////////////////////////////////////////////////////////////////////////
@ -138,3 +140,5 @@ private:
DEF_GM( return new ShadowsGM; )
}
#endif

View File

@ -41,6 +41,8 @@
#include <string.h>
#ifdef SK_SUPPORT_LEGACY_DRAWLOOPER
namespace skiagm {
constexpr int kWidth = 1250;
@ -274,3 +276,5 @@ private:
DEF_GM(return new TextBlobLooperGM;)
}
#endif

View File

@ -556,6 +556,7 @@ public:
*/
void setImageFilter(sk_sp<SkImageFilter> imageFilter);
#ifdef SK_SUPPORT_LEGACY_DRAWLOOPER
/** Returns SkDrawLooper if set, or nullptr.
Does not alter SkDrawLooper SkRefCnt.
@ -589,6 +590,7 @@ public:
(see skbug.com/6259)
*/
void setLooper(sk_sp<SkDrawLooper> drawLooper);
#endif
/** Returns true if SkPaint prevents all drawing;
otherwise, the SkPaint may or may not allow drawing.
@ -639,7 +641,10 @@ public:
SkPaint::Style style = this->getStyle();
// ultra fast-case: filling with no effects that affect geometry
if (kFill_Style == style) {
uintptr_t effects = reinterpret_cast<uintptr_t>(this->getLooper());
uintptr_t effects = 0;
#ifdef SK_SUPPORT_LEGACY_DRAWLOOPER
effects |= reinterpret_cast<uintptr_t>(this->getLooper());
#endif
effects |= reinterpret_cast<uintptr_t>(this->getMaskFilter());
effects |= reinterpret_cast<uintptr_t>(this->getPathEffect());
effects |= reinterpret_cast<uintptr_t>(this->getImageFilter());

View File

@ -20,6 +20,8 @@
#include "samplecode/Sample.h"
#include "src/utils/SkUTF.h"
#ifdef SK_SUPPORT_LEGACY_DRAWLOOPER
// effects
#include "include/effects/SkBlurDrawLooper.h"
#include "include/effects/SkGradientShader.h"
@ -158,3 +160,5 @@ private:
//////////////////////////////////////////////////////////////////////////////
DEF_SAMPLE( return new TilingView(); )
#endif

View File

@ -20,6 +20,8 @@
#include "tools/Resources.h"
#include "tools/ToolUtils.h"
#ifdef SK_SUPPORT_LEGACY_DRAWLOOPER
/**
* Interprets c as an unpremultiplied color, and returns the
* premultiplied equivalent.
@ -169,3 +171,5 @@ private:
//////////////////////////////////////////////////////////////////////////////
DEF_SAMPLE( return new UnpremulView(GetResourcePath("images")); )
#endif

View File

@ -110,7 +110,10 @@ bool SkCanvas::wouldOverwriteEntireSurface(const SkRect* rect, const SkPaint* pa
paintStyle == SkPaint::kStrokeAndFill_Style)) {
return false;
}
if (paint->getMaskFilter() || paint->getLooper()
if (paint->getMaskFilter()
#ifdef SK_SUPPORT_LEGACY_DRAWLOOPER
|| paint->getLooper()
#endif
|| paint->getPathEffect() || paint->getImageFilter()) {
return false; // conservative
}
@ -416,10 +419,13 @@ public:
// we remove the imagefilter/xfermode inside doNext()
}
#ifdef SK_SUPPORT_LEGACY_DRAWLOOPER
if (SkDrawLooper* looper = paint.getLooper()) {
fLooperContext = looper->makeContext(canvas, &fAlloc);
fIsSimple = false;
} else {
} else
#endif
{
fLooperContext = nullptr;
// can we be marked as simple?
fIsSimple = !fTempLayerForImageFilter;
@ -435,7 +441,9 @@ public:
const SkPaint& paint() const {
SkASSERT(fPaint);
#ifdef SK_SUPPORT_LEGACY_DRAWLOOPER
SkASSERT(fPaint->getDrawLooper() == nullptr); // we should have cleared this
#endif
return *fPaint;
}
@ -473,8 +481,10 @@ bool AutoDrawLooper::doNext() {
SkPaint* paint = fLazyPaintPerLooper.set(fLazyPaintInit.isValid() ?
*fLazyPaintInit.get() : fOrigPaint);
#ifdef SK_SUPPORT_LEGACY_DRAWLOOPER
// never want our downstream clients (i.e. devices) to see loopers
paint->setDrawLooper(nullptr);
#endif
if (fTempLayerForImageFilter) {
paint->setImageFilter(nullptr);
@ -2115,8 +2125,11 @@ void SkCanvas::onDrawPoints(PointMode mode, size_t count, const SkPoint pts[],
}
static bool needs_autodrawlooper(SkCanvas* canvas, const SkPaint& paint) {
return ((intptr_t)paint.getImageFilter() |
(intptr_t)paint.getLooper() ) != 0;
return ((intptr_t)paint.getImageFilter()
#ifdef SK_SUPPORT_LEGACY_DRAWLOOPER
| (intptr_t)paint.getLooper()
#endif
) != 0;
}
void SkCanvas::onDrawRect(const SkRect& r, const SkPaint& paint) {

View File

@ -20,7 +20,9 @@ bool SkDrawLooper::canComputeFastBounds(const SkPaint& paint) const {
for (;;) {
SkPaint p(paint);
if (context->next(&canvas, &p)) {
#ifdef SK_SUPPORT_LEGACY_DRAWLOOPER
p.setLooper(nullptr);
#endif
if (!p.canComputeFastBounds()) {
return false;
}
@ -47,7 +49,9 @@ void SkDrawLooper::computeFastBounds(const SkPaint& paint, const SkRect& s,
if (context->next(&canvas, &p)) {
SkRect r(src);
#ifdef SK_SUPPORT_LEGACY_DRAWLOOPER
p.setLooper(nullptr);
#endif
p.computeFastBounds(r, &r);
canvas.getTotalMatrix().mapRect(&r);

View File

@ -88,7 +88,9 @@ bool operator==(const SkPaint& a, const SkPaint& b) {
#define DEFINE_REF_FOO(type) sk_sp<Sk##type> SkPaint::ref##type() const { return f##type; }
DEFINE_REF_FOO(ColorFilter)
#ifdef SK_SUPPORT_LEGACY_DRAWLOOPER
DEFINE_REF_FOO(DrawLooper)
#endif
DEFINE_REF_FOO(ImageFilter)
DEFINE_REF_FOO(MaskFilter)
DEFINE_REF_FOO(PathEffect)
@ -181,9 +183,14 @@ MOVE_FIELD(Shader)
MOVE_FIELD(ColorFilter)
MOVE_FIELD(PathEffect)
MOVE_FIELD(MaskFilter)
#ifdef SK_SUPPORT_LEGACY_DRAWLOOPER
MOVE_FIELD(DrawLooper)
#endif
#undef MOVE_FIELD
#ifdef SK_SUPPORT_LEGACY_DRAWLOOPER
void SkPaint::setLooper(sk_sp<SkDrawLooper> looper) { fDrawLooper = std::move(looper); }
#endif
///////////////////////////////////////////////////////////////////////////////
@ -320,7 +327,9 @@ void SkPaintPriv::Flatten(const SkPaint& paint, SkWriteBuffer& buffer) {
paint.getShader() ||
paint.getMaskFilter() ||
paint.getColorFilter() ||
#ifdef SK_SUPPORT_LEGACY_DRAWLOOPER
paint.getLooper() ||
#endif
paint.getImageFilter()) {
flatFlags |= kHasEffects_FlatFlag;
}
@ -336,7 +345,11 @@ void SkPaintPriv::Flatten(const SkPaint& paint, SkWriteBuffer& buffer) {
buffer.writeFlattenable(paint.getShader());
buffer.writeFlattenable(paint.getMaskFilter());
buffer.writeFlattenable(paint.getColorFilter());
#ifdef SK_SUPPORT_LEGACY_DRAWLOOPER
buffer.writeFlattenable(paint.getLooper());
#else
buffer.write32(0);
#endif
buffer.writeFlattenable(paint.getImageFilter());
}
}
@ -387,14 +400,20 @@ SkReadPaintResult SkPaintPriv::Unflatten_PreV68(SkPaint* paint, SkReadBuffer& bu
paint->setMaskFilter(buffer.readMaskFilter());
paint->setColorFilter(buffer.readColorFilter());
(void)buffer.read32(); // use to be SkRasterizer
#ifdef SK_SUPPORT_LEGACY_DRAWLOOPER
paint->setLooper(buffer.readDrawLooper());
#else
(void)buffer.read32(); // used to be drawlooper
#endif
paint->setImageFilter(buffer.readImageFilter());
} else {
paint->setPathEffect(nullptr);
paint->setShader(nullptr);
paint->setMaskFilter(nullptr);
paint->setColorFilter(nullptr);
#ifdef SK_SUPPORT_LEGACY_DRAWLOOPER
paint->setLooper(nullptr);
#endif
paint->setImageFilter(nullptr);
}
@ -427,14 +446,20 @@ SkReadPaintResult SkPaintPriv::Unflatten(SkPaint* paint, SkReadBuffer& buffer, S
paint->setShader(buffer.readShader());
paint->setMaskFilter(buffer.readMaskFilter());
paint->setColorFilter(buffer.readColorFilter());
#ifdef SK_SUPPORT_LEGACY_DRAWLOOPER
paint->setLooper(buffer.readDrawLooper());
#else
(void)buffer.readDrawLooper();
#endif
paint->setImageFilter(buffer.readImageFilter());
} else {
paint->setPathEffect(nullptr);
paint->setShader(nullptr);
paint->setMaskFilter(nullptr);
paint->setColorFilter(nullptr);
#ifdef SK_SUPPORT_LEGACY_DRAWLOOPER
paint->setLooper(nullptr);
#endif
paint->setImageFilter(nullptr);
}
@ -483,9 +508,11 @@ bool SkPaint::getFillPath(const SkPath& src, SkPath* dst, const SkRect* cullRect
}
bool SkPaint::canComputeFastBounds() const {
#ifdef SK_SUPPORT_LEGACY_DRAWLOOPER
if (this->getLooper()) {
return this->getLooper()->canComputeFastBounds(*this);
}
#endif
if (this->getImageFilter() && !this->getImageFilter()->canComputeFastBounds()) {
return false;
}
@ -499,11 +526,13 @@ const SkRect& SkPaint::doComputeFastBounds(const SkRect& origSrc,
const SkRect* src = &origSrc;
if (this->getLooper()) {
#ifdef SK_SUPPORT_LEGACY_DRAWLOOPER
if (this->getLooper()) {
SkASSERT(this->getLooper()->canComputeFastBounds(*this));
this->getLooper()->computeFastBounds(*this, *src, storage);
return *storage;
}
#endif
SkRect tmpSrc;
if (this->getPathEffect()) {

View File

@ -98,7 +98,11 @@ static bool fold_opacity_layer_color_to_paint(const SkPaint* layerPaint,
// looper drawing unmodulated filter layer twice and then modulating the result produces
// different image to drawing modulated filter layer twice.
// TODO: most likely the looper and only some xfer modes are the hard constraints
if (!paint->isSrcOver() || paint->getLooper()) {
if (!paint->isSrcOver()
#ifdef SK_SUPPORT_LEGACY_DRAWLOOPER
|| paint->getLooper()
#endif
) {
return false;
}
@ -134,7 +138,9 @@ static bool fold_opacity_layer_color_to_paint(const SkPaint* layerPaint,
!layerPaint->isSrcOver() ||
layerPaint->getMaskFilter() ||
layerPaint->getColorFilter() ||
#ifdef SK_SUPPORT_LEGACY_DRAWLOOPER
layerPaint->getLooper() ||
#endif
layerPaint->getImageFilter()) {
return false;
}

View File

@ -814,7 +814,9 @@ static int lpaint_getEffects(lua_State* L) {
const SkPaint* paint = get_obj<SkPaint>(L, 1);
lua_newtable(L);
#ifdef SK_SUPPORT_LEGACY_DRAWLOOPER
setfield_bool_if(L, "looper", !!paint->getLooper());
#endif
setfield_bool_if(L, "pathEffect", !!paint->getPathEffect());
setfield_bool_if(L, "maskFilter", !!paint->getMaskFilter());
setfield_bool_if(L, "shader", !!paint->getShader());

View File

@ -50,8 +50,10 @@ DEF_TEST(Paint_copy, reporter) {
paint.setStyle(SkPaint::kStrokeAndFill_Style);
paint.setStrokeWidth(SkIntToScalar(2));
// set a few pointers
#ifdef SK_SUPPORT_LEGACY_DRAWLOOPER
SkLayerDrawLooper::Builder looperBuilder;
paint.setLooper(looperBuilder.detach());
#endif
paint.setMaskFilter(SkMaskFilter::MakeBlur(kNormal_SkBlurStyle,
SkBlurMask::ConvertRadiusToSigma(1)));
@ -179,7 +181,9 @@ DEF_TEST(Paint_MoreFlattening, r) {
SkPaint paint;
paint.setColor(0x00AABBCC);
paint.setBlendMode(SkBlendMode::kModulate);
#ifdef SK_SUPPORT_LEGACY_DRAWLOOPER
paint.setLooper(nullptr); // Default value, ignored.
#endif
SkBinaryWriteBuffer writer;
SkPaintPriv::Flatten(paint, writer);
@ -194,7 +198,9 @@ DEF_TEST(Paint_MoreFlattening, r) {
// No matter the encoding, these must always hold.
ASSERT(other.getColor() == paint.getColor());
#ifdef SK_SUPPORT_LEGACY_DRAWLOOPER
ASSERT(other.getLooper() == paint.getLooper());
#endif
ASSERT(other.getBlendMode() == paint.getBlendMode());
}

View File

@ -75,6 +75,7 @@ static void test_drawBitmap(skiatest::Reporter* reporter) {
canvas.drawBitmap(src, SkIntToScalar(-10), 0, &paint);
REPORTER_ASSERT(reporter, 0 == *dst.getAddr32(5, 5));
#ifdef SK_SUPPORT_LEGACY_DRAWLOOPER
// now install our looper, which will draw, since it internally translates
// to the left. The test is to ensure that canvas' quickReject machinary
// allows us through, even though sans-looper we would look like we should
@ -82,6 +83,7 @@ static void test_drawBitmap(skiatest::Reporter* reporter) {
paint.setLooper(sk_make_sp<TestLooper>());
canvas.drawBitmap(src, SkIntToScalar(-10), 0, &paint);
REPORTER_ASSERT(reporter, 0xFFFFFFFF == *dst.getAddr32(5, 5));
#endif
}
static void test_layers(skiatest::Reporter* reporter) {
@ -166,6 +168,7 @@ DEF_TEST(QuickReject_MatrixState, reporter) {
canvas.quickReject(SkRect::MakeWH(100.0f, 100.0f));
}
#ifdef SK_SUPPORT_LEGACY_DRAWLOOPER
#include "include/core/SkSurface.h"
#include "include/effects/SkLayerDrawLooper.h"
DEF_TEST(looper_nothingtodraw, reporter) {
@ -191,3 +194,4 @@ DEF_TEST(looper_nothingtodraw, reporter) {
// See https://skia-review.googlesource.com/c/skia/+/121220
surf->getCanvas()->drawRect({1, 1, 10, 10}, paint);
}
#endif

View File

@ -948,7 +948,9 @@ void DrawCommand::MakeJsonPaint(SkJSONWriter& writer,
apply_paint_patheffect(paint, writer, urlDataManager);
apply_paint_maskfilter(paint, writer, urlDataManager);
apply_flattenable(DEBUGCANVAS_ATTRIBUTE_SHADER, paint.getShader(), writer, urlDataManager);
#ifdef SK_SUPPORT_LEGACY_DRAWLOOPER
apply_flattenable(DEBUGCANVAS_ATTRIBUTE_LOOPER, paint.getLooper(), writer, urlDataManager);
#endif
apply_flattenable(
DEBUGCANVAS_ATTRIBUTE_IMAGEFILTER, paint.getImageFilter(), writer, urlDataManager);
apply_flattenable(